BZOJ4811: [Ynoi2017]由乃的OJ 重链剖分
2017-04-11 16:57
246 查看
题意:起床困难综合征出到树上,带单点修改和区间询问
很容易想到在线段树上维护每一位遍历所有操作后会变成什么,但是第一次交TLE了。。。
然后发现我以前写了假的《又是nand》。。。我说怎么跑得这么慢。。。
维护上面说的这个东西并不需要64*2个bool变量,而是可以压到两个unsigned long long里,分别代表每一位输入为0和每一位输入为1。
将两个合并:若输入为0,经过左变量后某些bit会变成1,这些bit在输出中与”若输入为1”的右变量那些bit保持一致,其余bit与”若输入为0”的右变量那些bit保持一致,可得:
c.x0=(a.x0&b.x1)|(~a.x0&b.x0)
另一个同理。c.x1=(a.x1&b.x1)|(~a.x1&b.x0)
于是树剖就可以维护了。得到信息后从高位到低位贪心能选就选。
代码:
很容易想到在线段树上维护每一位遍历所有操作后会变成什么,但是第一次交TLE了。。。
然后发现我以前写了假的《又是nand》。。。我说怎么跑得这么慢。。。
维护上面说的这个东西并不需要64*2个bool变量,而是可以压到两个unsigned long long里,分别代表每一位输入为0和每一位输入为1。
将两个合并:若输入为0,经过左变量后某些bit会变成1,这些bit在输出中与”若输入为1”的右变量那些bit保持一致,其余bit与”若输入为0”的右变量那些bit保持一致,可得:
c.x0=(a.x0&b.x1)|(~a.x0&b.x0)
另一个同理。c.x1=(a.x1&b.x1)|(~a.x1&b.x0)
于是树剖就可以维护了。得到信息后从高位到低位贪心能选就选。
代码:
#include<cstdio> #include<cstring> #define gm 100001 using namespace std; typedef unsigned long long ll; int n,m,k; struct Istream { static const size_t str=1<<16; char buf[str],*s,*t; Istream():buf(),s(),t(){} char get() { return (s==t)?(t=buf+fread(s=buf,1,str,stdin),*s++):(*s++); } Istream& operator >> (int &x) { register char c; do c=get(); while(c<'0'||c>'9'); x=0; while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=get(); return *this; } Istream& operator>> (ll &x) { register char c; do c=get(); while(c<'0'||c>'9'); x=0; while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=get(); return *this; } }cin; struct Ostream { static const size_t str=1<<16; char buf[str],*s,*t; Ostream():buf(),s(buf),t(buf+str){} ~Ostream(){fwrite(buf,1,s-buf,stdout);} void put(char c) { (s==t)?(fwrite(s=buf,1,str,stdout),*s++=c):(*s++=c); } Ostream& operator<< (ll x) { if(!x) { return put('0'),*this; } char a[22],t=1; while(x) a[t++]=x%10,x/=10; while(--t) put(a[t]+'0'); return *this; } Ostream& operator<< (const char *x) { while(*x) put(*x++); return *this; } }cout; const char *endl="\n"; struct info { ll a,b; info(){} info(const ll &x,int opt) { switch(opt) { case 1: a=0,b=x; break; case 2: a=x,b=~0ull; break; default: a=x,b=~x; } } info(const ll &a,const ll &b):a(a),b(b){} bool operator () (int x,int y) { return y?(b>>x&1ull):(a>>x&1ull); } info operator + (const info &v) const { return info((a&v.b)|(~a&v.a),(b&v.b)|(~b&v.a)); } }pre[262144],suf[262144],nil; int op[gm]; ll val[gm]; ll pool[gm<<1],*ptr=pool; struct e { int t; e *n; e(int t,e *n):t(t),n(n){} inline void* operator new(size_t){return ++ptr;} }*f[gm]; int sz[gm],fa[gm],son[gm],dfn[gm],dep[gm],top[gm],ord[gm],ct=0; void dfs1(int x=1) { sz[x]=1; for(e *i=f[x];i;i=i->n) { if(i->t==fa[x]) continue; fa[i->t]=x; dep[i->t]=dep[x]+1; dfs1(i->t); sz[x]+=sz[i->t]; if(sz[i->t]>=sz[son[x]]) son[x]=i->t; } } void dfs2(int x=1) { ord[dfn[x]=++ct]=x; top[x]=(x==son[fa[x]]?top[fa[x]]:x); if(son[x]) dfs2(son[x]); for(e *i=f[x];i;i=i->n) { if(i->t==fa[x]||i->t==son[x]) continue; dfs2(i->t); } } void build(int l=1,int r=n,int o=1) { if(l==r) { pre[o]=suf[o]=info(val[ord[l]],op[ord[l]]); return; } int mid=l+r>>1,ls=o<<1,rs=ls|1; build(l,mid,ls); build(mid+1,r,rs); pre[o]=pre[ls]+pre[rs]; suf[o]=suf[rs]+suf[ls]; } int x,y; void cast(int l=1,int r=n,int o=1) { if(l==r) { pre[o]=suf[o]=info(val[ord[l]],op[ord[l]]); return; } int mid=l+r>>1,ls=o<<1,rs=ls|1; if(x<=mid) cast(l,mid,ls); else cast(mid+1,r,rs); pre[o]=pre[ls]+pre[rs]; suf[o]=suf[rs]+suf[ls]; } info getpr(int l=1,int r=n,int o=1) { if(x<=l&&r<=y) { return pre[o]; } int mid=l+r>>1,ls=o<<1,rs=ls|1; if(y<=mid) return getpr(l,mid,ls); if(mid<x) return getpr(mid+1,r,rs); return getpr(l,mid,ls)+getpr(mid+1,r,rs); } info getsf(int l=1,int r=n,int o=1) { if(x<=l&&r<=y) { return suf[o]; } int mid=l+r>>1,ls=o<<1,rs=ls|1; if(y<=mid) return getsf(l,mid,ls); if(mid<x) return getsf(mid+1,r,rs); return getsf(mid+1,r,rs)+getsf(l,mid,ls); } int LCA(int a,int b) { while(top[a]!=top[b]) { if(dep[top[a]]<dep[top[b]]) a^=b^=a^=b; a=fa[top[a]]; } return dep[a]<dep[b]?a:b; } info query(int a,int b) { int lca=LCA(a,b); info ra=nil,rb=nil,res; while(top[a]!=top[lca]) { x=dfn[top[a]],y=dfn[a]; ra=ra+getsf(); a=fa[top[a]]; } x=dfn[lca],y=dfn[a]; ra=ra+getsf(); while(top[b]!=top[lca]) { x=dfn[top[b]],y=dfn[b]; rb=getpr()+rb; b=fa[top[b]]; } if(b!=lca) { x=dfn[lca]+1,y=dfn[b]; rb=getpr()+rb; } return ra+rb; } int main() { cin>>n>>m>>k; nil.a=0,nil.b=(k==64?~0ull:(1ull<<k)-1); for(int i=1;i<=n;++i) cin>>op[i]>>val[i]; for(int i=1;i<n;++i) { int u,v; cin>>u>>v; f[u]=new e(v,f[u]); f[v]=new e(u,f[v]); } dfs1(),dfs2(),build(); for(int i=1;i<=m;++i) { int tp,x,y; ll z; cin>>tp>>x>>y>>z; if(tp==1) { info res=query(x,y); ll ans=0,kre=0; for(int i=k-1;~i;--i) { if(res(i,0)) ans|=1ull<<i; else if(res(i,1)&&(kre|(1ull<<i))<=z) kre|=1ull<<i,ans|=1ull<<i; } cout<<ans<<endl; } else { op[x]=y,val[x]=z; ::x=dfn[x]; cast(); } } return 0; }
相关文章推荐
- BZOJ4811 [Ynoi2017]由乃的OJ
- BZOJ4811: [Ynoi2017]由乃的OJ(洛谷P3613)
- 【BZOJ4811】[Ynoi2017]由乃的OJ 树链剖分+线段树
- BZOJ-4811: [Ynoi2017]由乃的OJ (树链剖分 线段树维护区间操作值 好题)
- [树链剖分] BZOJ 4811 [Ynoi2017]由乃的OJ
- BZOJ 4811 [Ynoi2017]由乃的OJ ——Link-Cut Tree
- bzoj 4811: [Ynoi2017]由乃的OJ (树链剖分)
- BZOJ 4811([Ynoi2017]由乃的OJ-树链剖分)
- 4811: [Ynoi2017]由乃的OJ
- bzoj 4811: [Ynoi2017]由乃的OJ
- [bzoj4811] [Ynoi2017]由乃的OJ
- bzoj 4811: [Ynoi2017]由乃的OJ
- [YNOI2017][bzoj4811][luogu3613] 由乃的OJ/睡觉困难综合症 [压位+树链剖分+线段树]
- BZOJ4811 [Ynoi2017]由乃的OJ
- bzoj 4866: [Ynoi2017]由乃的商场之旅 莫队算法
- 4810: [Ynoi2017]由乃的玉米田
- bzoj4810: [Ynoi2017]由乃的玉米田
- [莫队 bitset] BZOJ 4810 [Ynoi2017]由乃的玉米田
- [bzoj4810][Ynoi2017]由乃的玉米田
- [BZOJ4811][Ynoi2017]由乃的OJ 树链剖分+线段树