luogu3613 睡觉困难综合征(lct+贪心)
2018-03-08 23:27
323 查看
是bzoj3668的改编。
如果我们知道了每一位上取0和取1时的结果,我们就可以直接从高位开始贪心了。
于是每个节点维护一下每一位取0时的答案f0,每
4000
一位取1时的答案f1(当然是按中序遍历做咯)。考虑如何合并两个答案呢?记左边为a,右边为b,结果为res,则有
res.f0=(~a.f0&b.f0)|(a.f0&b.f1)
res.f1=(~a.f1&b.f0)|(a.f1&b.f1)
脑补一下就好啦。
然后因为有翻转操作,我们不仅要记正着的答案(即从左到右),还要记反着的答案(即从右到左)。然后比较坑的要开ull。
如果我们知道了每一位上取0和取1时的结果,我们就可以直接从高位开始贪心了。
于是每个节点维护一下每一位取0时的答案f0,每
4000
一位取1时的答案f1(当然是按中序遍历做咯)。考虑如何合并两个答案呢?记左边为a,右边为b,结果为res,则有
res.f0=(~a.f0&b.f0)|(a.f0&b.f1)
res.f1=(~a.f1&b.f0)|(a.f1&b.f1)
脑补一下就好啦。
然后因为有翻转操作,我们不仅要记正着的答案(即从左到右),还要记反着的答案(即从右到左)。然后比较坑的要开ull。
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define ll unsigned long long #define inf 0x3f3f3f3f #define N 100010 inline char gc(){ static char buf[1<<16],*S,*T; if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(S==T) return EOF;} return *S++; } inline ll read(){ ll x=0,f=1;char ch=gc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f; } int n,m,Z,fa ,c [2],q ;ll tot,bin[66];bool rev ; struct data{ ll f0,f1; friend data operator+(data a,data b){ data res; res.f0=(~a.f0&b.f0)|(a.f0&b.f1); res.f1=(~a.f1&b.f0)|(a.f1&b.f1);return res; } }ls ,rs ,v ; inline ll cal(ll x,int op,ll y){ if(op==1) return x&y; if(op==2) return x|y; if(op==3) return x^y; } inline bool isroot(int x){return x!=c[fa[x]][0]&&x!=c[fa[x]][1];} inline void dorev(int x){ if(!x) return; rev[x]^=1;swap(c[x][0],c[x][1]);swap(ls[x],rs[x]); } inline void update(int p){ int l=c[p][0],r=c[p][1];ls[p]=rs[p]=v[p]; if(l) ls[p]=ls[l]+ls[p],rs[p]=rs[p]+rs[l]; if(r) ls[p]=ls[p]+ls[r],rs[p]=rs[r]+rs[p]; } inline void pushdown(int p){ if(!rev[p]) return;rev[p]=0; dorev(c[p][0]);dorev(c[p][1]); } inline void rotate(int x){ int y=fa[x],z=fa[y],l=x==c[y][1],r=l^1; if(!isroot(y)) c[z][y==c[z][1]]=x; fa[c[x][r]]=y;fa[y]=x;fa[x]=z; c[y][l]=c[x][r];c[x][r]=y;update(y);update(x); } inline void splay(int x){ int top=0;q[++top]=x; for(int xx=x;!isroot(xx);xx=fa[xx]) q[++top]=fa[xx]; while(top) pushdown(q[top--]); while(!isroot(x)){ int y=fa[x],z=fa[y]; if(!isroot(y)){ if(x==c[y][1]^y==c[z][1]) rotate(x); else rotate(y); }rotate(x); } } inline void access(int x){ int y=0;while(x){splay(x);c[x][1]=y;update(x);y=x;x=fa[x];} } inline void makeroot(int x){ access(x);splay(x);dorev(x); } inline void link(int x,int y){ makeroot(x);fa[x]=y; } inline ll query(int x,int y,ll z){ makeroot(x);access(y);splay(y);ll ans=0; for(int i=Z-1;i>=0;--i){ if(ls[y].f0>>i&1) ans+=bin[i]; else if((ls[y].f1>>i&1)&&z>=bin[i]) ans+=bin[i],z-=bin[i]; }return ans; } inline void change(int x,int op,ll z){ splay(x);v[x].f0=cal(0,op,z);v[x].f1=cal(tot,op,z);update(x); } int main(){ // freopen("a.in","r",stdin); n=read();m=read();Z=read();bin[0]=1; for(int i=1;i<=Z;++i) bin[i]=bin[i-1]<<1;tot=bin[Z]-1; for(int i=1;i<=n;++i){ int op=read();ll x=read(); v[i].f0=ls[i].f0=rs[i].f0=cal(0,op,x); v[i].f1=ls[i].f1=rs[i].f1=cal(tot,op,x); }for(int i=1;i<n;++i){ int x=read(),y=read();link(x,y); }while(m--){ int op=read(),x=read(),y=read();ll z=read(); if(op==1) printf("%llu\n",query(x,y,z)); else change(x,y,z); }return 0; }
相关文章推荐
- luogu3613 睡觉困难综合征
- Luogu3613 睡觉困难综合征
- Luogu3613 睡觉困难综合征
- Luogu 睡觉困难综合征 ([NOI2014]起床困难综合症)
- 洛谷P3613 睡觉困难综合征
- 【NOI 2014】起床困难综合征 拆位+贪心
- luogu P3613 睡觉困难综合征
- [洛谷]P3613 睡觉困难综合征
- [YNOI2017][bzoj4811][luogu3613] 由乃的OJ/睡觉困难综合症 [压位+树链剖分+线段树]
- 洛谷P3613:睡觉困难综合征 (LCT+二进制压位)
- [BZOJ3668]NOI2014起床困难综合征|贪心
- 洛谷3613:睡觉困难综合症(LCT+机巧的位运算)
- 省队集训Day1 睡觉困难综合征
- 【树链剖分】LGP3613 睡觉困难综合征
- 洛谷P3613 睡觉困难综合征
- 【bzoj3668】【noi 2014】【起床困难综合症】【贪心】
- [bzoj3668][Noi2014][起床困难综合症] (按位贪心)
- 【贪心】BZOJ3668 [Noi2014]起床困难综合症
- 【BZOJ】3668 [Noi2014]起床困难综合症 贪心
- [BZOJ3688][Noi2014]起床困难综合症 && 贪心