题解:
对于每一个节点,我们建立v0,v1
v0表示0进过会怎么样
v1表示1进过会怎么样
然后线段树合并
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=100005; typedef unsigned long long ull; ull a[N],zz,now,ans; int n,m,k,op,xx,yy,Op[N],fi[N],ne[N*2],v[N*2],tot; int size[N],fa[N],son[N],deep[N],rev[N],dfn[N],cnt,top[N]; struct Tree { ull v0,v1;Tree(){} Tree(int op,ull x) { if (op==1)v0=0,v1=x; else if (op==2)v0=x,v1=~0; else v0=x,v1=(~0)^x; } Tree(ull x,ull y){v0=x,v1=y;} }trl[N*8],trr[N*8]; Tree operator+(Tree x,Tree y) { return Tree((x.v0&y.v1)|((~x.v0)&y.v0),(x.v1&y.v1)|((~x.v1)&y.v0)); } void jb(int x,int y) { v[tot]=y; ne[tot]=fi[x]; fi[x]=tot++; } void dfs1(int x) { size[x]=1; for (int i=fi[x];~i;i=ne[i]) if (v[i]!=fa[x]) { fa[v[i]]=x; deep[v[i]]=deep[x]+1; dfs1(v[i]); size[x]+=size[v[i]]; if (size[v[i]]>size[son[x]])son[x]=v[i]; } } void dfs2(int x,int tp) { rev[dfn[x]=++cnt]=x; top[x]=tp; if (son[x])dfs2(son[x],tp); for (int i=fi[x];~i;i=ne[i]) if (v[i]!=fa[x]&&v[i]!=son[x])dfs2(v[i],v[i]); } void build(int l,int r,int pos) { if (l==r) { trl[pos]=trr[pos]=Tree(Op[rev[l]],a[rev[l]]); return; } int mid=(l+r)>>1; build(l,mid,pos*2); build(mid+1,r,pos*2+1); trl[pos]=trl[pos*2]+trl[pos*2+1]; trr[pos]=trr[pos*2+1]+trr[pos*2]; } void insert(int l,int r,int pos,int num) { if (l==r) { trl[pos]=trr[pos]=Tree(Op[rev[l]],a[rev[l]]); return; } int mid=(l+r)>>1; if (mid<num)insert(mid+1,r,pos*2+1,num); else insert(l,mid,pos*2,num); trl[pos]=trl[pos*2]+trl[pos*2+1]; trr[pos]=trr[pos*2+1]+trr[pos*2]; } Tree query(int l,int r,int pos,int L,int R,int f) { if (l>=L&&r<=R)return f?trr[pos]:trl[pos]; int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1; if (mid<L)return query(mid+1,r,pos*2+1,L,R,f); if (mid>=R)return query(l,mid,pos*2,L,R,f); if (!f)return query(l,mid,pos*2,L,R,f)+query(mid+1,r,pos*2+1,L,R,f); return query(mid+1,r,pos*2+1,L,R,f)+query(l,mid,pos*2,L,R,f); } Tree solve(int x,int y) { Tree vx=Tree((int)3,0ull),vy=Tree((int)3,0ull); int fx=top[x],fy=top[y]; while (fx!=fy) if (deep[fx]>deep[fy]) { vx=vx+query(1,n,1,dfn[fx],dfn[x],1); x=fa[fx]; fx=top[x]; } else { vy=query(1,n,1,dfn[fy],dfn[y],0)+vy; y=fa[fy]; fy=top[y]; } if (deep[x]>deep[y])return vx+query(1,n,1,dfn[y],dfn[x],1)+vy; return vx+query(1,n,1,dfn[x],dfn[y],0)+vy; } int main() { memset(fi,-1,sizeof(fi)); deep[1]=1; scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=n;i++)scanf("%d%llu",&Op[i],&a[i]); for (int i=1;i<n;i++) { scanf("%d%d",&xx,&yy); jb(xx,yy);jb(yy,xx); } dfs1(1);dfs2(1,1); build(1,n,1); while (m--) { scanf("%d%d%d%llu",&op,&xx,&yy,&zz); if (op==2)Op[xx]=yy,a[xx]=zz,insert(1,n,1,dfn[xx]); else { Tree t=solve(xx,yy);now=ans=0; for (int i=k-1;~i;i--) if (t.v0&(1ull<<i))ans+=1ull<<i; else if (t.v1&(1ull<<i)&&now+(1ull<<i)<=zz) { now+=1ull<<i; ans+=1ull<<i; } printf("%llu\n",ans); } } return 0; }