如果做过起床困难综合征的话应该很快就能有思路,没做过那道题的话还真是挺费劲的.
我们不知道要带入的值是什么,但是我们可以知道假设带入值得当前位为 $1$ 时这一位在经过位运算后是否为 $1$.
至于这个怎么维护,我们开两个变量 $f0,f1$ 代表初始带入全 $0$,全 $1$ 时每一位得值.
然后在 $LCT$ 中维护从左向右,从右向左两个方向上得这个东西,注意一下 $pushup$ 函数得写法.
这段代码十分优美,利用了按位取反等骚操作:
struct node { ll f0,f1; node operator+(const node &b) const { node a; a.f0=(~f0&b.f0)|(f0&b.f1); a.f1=(~f1&b.f0)|(f1&b.f1); return a; } }f[N],L[N],R[N];
code:
#include <bits/stdc++.h> #define N 100007 #define ll unsigned long long #define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout) using namespace std; int n,m,k,edges; int hd[N],to[N<<1],nex[N<<1]; void addedge(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } struct node { ll f0,f1; node operator+(const node &b) const { node a; a.f0=(~f0&b.f0)|(f0&b.f1); a.f1=(~f1&b.f0)|(f1&b.f1); return a; } }f[N],L[N],R[N]; struct Link_Cut_Tree { #define lson p[x].ch[0] #define rson p[x].ch[1] int sta[N]; struct Node { int ch[2],f,rev; }p[N]; int get(int x) { return p[p[x].f].ch[1]==x; } int isrt(int x) { return !(p[p[x].f].ch[0]==x||p[p[x].f].ch[1]==x); } void pushup(int x) { L[x]=R[x]=f[x]; if(lson) L[x]=L[lson]+L[x], R[x]=R[x]+R[lson]; if(rson) L[x]=L[x]+L[rson], R[x]=R[rson]+R[x]; } void rotate(int x) { int old=p[x].f,fold=p[old].f,which=get(x); if(!isrt(old)) p[fold].ch[p[fold].ch[1]==old]=x; p[old].ch[which]=p[x].ch[which^1],p[p[old].ch[which]].f=old; p[x].ch[which^1]=old,p[old].f=x,p[x].f=fold; pushup(old),pushup(x); } void mark(int x) { if(!x) return; swap(lson,rson), swap(L[x],R[x]),p[x].rev^=1; } void pushdown(int x) { if(p[x].rev) { p[x].rev=0; if(lson) mark(lson); if(rson) mark(rson); } } void splay(int x) { int u=x,v=0,fa; for(sta[++v]=u;!isrt(u);u=p[u].f) sta[++v]=p[u].f; for(;v;--v) pushdown(sta[v]); for(u=p[u].f;(fa=p[x].f)!=u;rotate(x)) if(p[fa].f!=u) rotate(get(fa)==get(x)?fa:x); } void Access(int x) { for(int y=0;x;y=x,x=p[x].f) { splay(x); rson=y; pushup(x); } } void makeroot(int x) { Access(x),splay(x),mark(x); } void split(int x,int y) { makeroot(x), Access(y), splay(y); } void link(int x,int y) { makeroot(x), p[x].f=y; } void cut(int x,int y) { makeroot(x),Access(y),splay(y); p[y].ch[0]=p[x].f=0; pushup(y); } #undef lson #undef rson }lct; void solve(int x,int y,ll z) { lct.split(x,y); int i; ll re=0; for(i=k-1;i>=0;--i) { if(L[y].f0&(1ll<<i)) re+=(1ll<<i); else if((L[y].f1&(1ll<<i)) && (1ll<<i)<=z) re+=(1ll<<i), z-=(1ll<<i); } printf("%llu ",re); } void dfs(int u,int ff) { lct.p[u].f=ff; for(int i=hd[u];i;i=nex[i]) if(to[i]!=ff) dfs(to[i],u); } int main() { int i,j; // setIO("input"); scanf("%d%d%d",&n,&m,&k); for(i=1;i<=n;++i) { int op; ll y; scanf("%d%llu",&op,&y); if(op==1) f[i]=(node){0ll,y}; if(op==2) f[i]=(node){y,~0ll}; if(op==3) f[i]=(node){y,~y}; lct.pushup(i); } for(i=1;i<n;++i) { int u,v; scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u); } dfs(1,0); for(i=1;i<=m;++i) { int op; scanf("%d",&op); if(op==1) { int x,y; ll z; scanf("%d%d%llu",&x,&y,&z); solve(x,y,z); } else { int x,y; ll z; scanf("%d%d%llu",&x,&y,&z); lct.Access(x); lct.splay(x); if(y==1) f[x]=(node){0ll,z}; if(y==2) f[x]=(node){z,~0ll}; if(y==3) f[x]=(node){z,~z}; lct.pushup(x); } } return 0; }