这道题树链剖分或是动态树都可以做(不过我的动态树BZOJ上TLE了,可见LCT常数很大),思路什么的不会看别人的博客就好,这里就不多扯了。
这里贴一个:
https://www.cnblogs.com/Narh/p/9171362.html
树链剖分代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define ls (o<<1) 5 #define rs ((o<<1)|1) 6 #define mid ((l+r)>>1) 7 using namespace std; 8 typedef unsigned long long LL; 9 inline LL read(){ 10 LL x=0;char ch=getchar(); 11 while(ch<'0'||ch>'9')ch=getchar(); 12 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 13 return x; 14 } 15 const int SIZE=100005; 16 const LL U=-1; 17 int n,m,k; 18 int typ[SIZE];LL num[SIZE]; 19 int fa[SIZE],dep[SIZE],pc[SIZE],siz[SIZE],top[SIZE],id[SIZE],tot; 20 int op[SIZE],loc,ktyp,ql,qr; 21 LL w[SIZE],knum; 22 struct Node{ 23 LL l[2],r[2]; 24 }; 25 Node S,a[SIZE*4],sav[2][SIZE]; 26 int len[2]; 27 int head[SIZE],ecnt; 28 struct Edge{ 29 int to,next; 30 }e[SIZE*2]; 31 void add_edge(int bg,int ed){ 32 ecnt++; 33 e[ecnt].next=head[bg]; 34 e[ecnt].to=ed; 35 head[bg]=ecnt; 36 } 37 void dfs1(int x,int pre,int depth){ 38 fa[x]=pre; 39 dep[x]=depth; 40 siz[x]=1; 41 int maxsiz=-1; 42 for(int i=head[x];i;i=e[i].next){ 43 int go=e[i].to; 44 if(go==pre) continue; 45 dfs1(go,x,depth+1); 46 siz[x]+=siz[go]; 47 if(siz[go]>maxsiz){ 48 maxsiz=siz[go]; 49 pc[x]=go; 50 } 51 } 52 } 53 void dfs2(int x,int topf){ 54 top[x]=topf; 55 id[x]=++tot; 56 op[tot]=typ[x]; 57 w[tot]=num[x]; 58 if(!pc[x]) return; 59 dfs2(pc[x],topf); 60 for(int i=head[x];i;i=e[i].next){ 61 int go=e[i].to; 62 if(go==fa[x]||go==pc[x]) continue; 63 dfs2(go,go); 64 } 65 } 66 Node trans(int p,LL x){ 67 Node ans; 68 if(p==1){ 69 ans.l[0]=ans.r[0]=(x&0); 70 ans.l[1]=ans.r[1]=(x&U); 71 } 72 if(p==2){ 73 ans.l[0]=ans.r[0]=(x|0); 74 ans.l[1]=ans.r[1]=(x|U); 75 } 76 if(p==3){ 77 ans.l[0]=ans.r[0]=(x^0); 78 ans.l[1]=ans.r[1]=(x^U); 79 } 80 return ans; 81 } 82 Node merge(Node x,Node y){ 83 Node ans; 84 ans.l[0]=((x.l[0]&y.l[1])|((~x.l[0])&y.l[0])); 85 ans.l[1]=((x.l[1]&y.l[1])|((~x.l[1])&y.l[0])); 86 ans.r[0]=((y.r[0]&x.r[1])|((~y.r[0])&x.r[0])); 87 ans.r[1]=((y.r[1]&x.r[1])|((~y.r[1])&x.r[0])); 88 return ans; 89 } 90 Node rev(Node x){ 91 swap(x.l[0],x.r[0]); 92 swap(x.l[1],x.r[1]); 93 return x; 94 } 95 void pushup(int o){ 96 a[o]=merge(a[ls],a[rs]); 97 } 98 void build(int o,int l,int r){ 99 if(l==r){ 100 a[o]=trans(op[l],w[l]); 101 return; 102 } 103 build(ls,l,mid); 104 build(rs,mid+1,r); 105 pushup(o); 106 } 107 void update(int o,int l,int r){ 108 if(l==r&&l==loc){ 109 a[o]=trans(ktyp,knum); 110 return; 111 } 112 if(loc<=mid) update(ls,l,mid); 113 else update(rs,mid+1,r); 114 pushup(o); 115 } 116 Node query(int o,int l,int r){ 117 if(ql<=l&&r<=qr) 118 return a[o]; 119 Node ans=S; 120 if(mid>=ql) ans=merge(ans,query(ls,l,mid)); 121 if(mid<qr) ans=merge(ans,query(rs,mid+1,r)); 122 return ans; 123 } 124 Node statistic(int x,int y){ 125 len[0]=len[1]=0; 126 int r=1; 127 while(top[x]!=top[y]){ 128 if(dep[top[x]]<dep[top[y]]){ 129 swap(x,y); 130 r^=1; 131 } 132 ql=id[top[x]],qr=id[x]; 133 sav[r][++len[r]]=query(1,1,n); 134 x=fa[top[x]]; 135 } 136 r^=1; 137 if(dep[x]>dep[y]){ 138 swap(x,y); 139 r^=1; 140 } 141 ql=id[x],qr=id[y]; 142 sav[r][++len[r]]=query(1,1,n); 143 Node ans=S; 144 for(int i=1;i<=len[1];i++) 145 ans=merge(ans,rev(sav[1][i])); 146 for(int i=len[0];i;i--) 147 ans=merge(ans,sav[0][i]); 148 return ans; 149 } 150 LL greedy_algo(Node x,LL z){ 151 LL ans=0; 152 for(int i=63;i+1;i--){ 153 if((x.l[0]>>i)&1){ 154 ans+=((LL)1<<i); 155 continue; 156 } 157 if(((LL)1<<i)<=z&&((x.l[1]>>i)&1)){ 158 ans+=((LL)1<<i); 159 z-=((LL)1<<i); 160 continue; 161 } 162 } 163 return ans; 164 } 165 int main(){ 166 S.l[0]=S.r[0]=0; 167 S.l[1]=S.r[1]=U; 168 n=read();m=read();k=read(); 169 for(int i=1;i<=n;i++){ 170 typ[i]=read(); 171 num[i]=read(); 172 } 173 for(int i=1;i<n;i++){ 174 int u=read(),v=read(); 175 add_edge(u,v); 176 add_edge(v,u); 177 } 178 dfs1(1,0,1); 179 dfs2(1,1); 180 build(1,1,n); 181 while(m--){ 182 int opt=read(); 183 if(opt==1){ 184 int x=read(),y=read(); 185 LL z=read(); 186 Node rez=statistic(x,y); 187 LL ans=greedy_algo(rez,z); 188 printf("%llu\n",ans); 189 } 190 else if(opt==2){ 191 loc=read(),ktyp=read(); 192 knum=read(); 193 loc=id[loc]; 194 update(1,1,n); 195 } 196 } 197 return 0; 198 }
动态树(LCT)代码:
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 typedef unsigned long long LL; 5 inline LL read(){ 6 LL x=0,f=1;char ch=getchar(); 7 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 8 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 9 return x*f; 10 } 11 const int MAXN=100005; 12 const LL U=-1; 13 int n,m,k,fa[MAXN],ch[MAXN][2],tag[MAXN],stack[MAXN],top; 14 struct Node{ 15 LL l0,l1,r0,r1; 16 friend Node operator + (Node lf,Node rt){ 17 Node ans; 18 ans.l0=((lf.l0&rt.l1)|((~lf.l0)&rt.l0)); 19 ans.l1=((lf.l1&rt.l1)|((~lf.l1)&rt.l0)); 20 ans.r0=((rt.r0&lf.r1)|((~rt.r0)&lf.r0)); 21 ans.r1=((rt.r1&lf.r1)|((~rt.r1)&lf.r0)); 22 return ans; 23 } 24 }a[MAXN],b[MAXN]; 25 #define lc ch[x][0] 26 #define rc ch[x][1] 27 inline bool isroot(int x){ 28 return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; 29 } 30 inline void pushup(int x){ 31 b[x]=(b[lc]+a[x])+b[rc]; 32 } 33 inline void pushr(int x){ 34 swap(lc,rc); 35 swap(b[x].l0,b[x].r0); 36 swap(b[x].l1,b[x].r1); 37 tag[x]^=1; 38 } 39 inline void pushdown(int x){ 40 if(!tag[x]) return; 41 if(lc) pushr(lc); 42 if(rc) pushr(rc); 43 tag[x]=0; 44 } 45 inline void calc(int x,int opt,LL k){ 46 if(opt==1){ 47 a[x].l0=a[x].r0=(0&k); 48 a[x].l1=a[x].r1=(U&k); 49 } 50 else if(opt==2){ 51 a[x].l0=a[x].r0=(0|k); 52 a[x].l1=a[x].r1=(U|k); 53 } 54 else{ 55 a[x].l0=a[x].r0=(0^k); 56 a[x].l1=a[x].r1=(U^k); 57 } 58 b[x]=a[x]; 59 } 60 inline void rotate(int x){ 61 int y=fa[x],z=fa[y],f=(ch[y][1]==x),g=ch[x][f^1]; 62 if(!isroot(y)) ch[z][ch[z][1]==y]=x; 63 ch[x][f^1]=y; 64 ch[y][f]=g; 65 if(g) fa[g]=y; 66 fa[y]=x; 67 fa[x]=z; 68 pushup(y); 69 pushup(x); 70 } 71 inline void splay(int x){ 72 int y=x,z; 73 stack[top=1]=y; 74 while(!isroot(y)) stack[++top]=(y=fa[y]); 75 while(top) pushdown(stack[top--]); 76 while(!isroot(x)){ 77 y=fa[x],z=fa[y]; 78 if(!isroot(y)){ 79 if((ch[y][0]==x)^(ch[z][0]==y)) rotate(x); 80 else rotate(y); 81 } 82 rotate(x); 83 } 84 } 85 inline void access(int x){ 86 for(int y=0;x;x=fa[y=x]){ 87 splay(x); 88 rc=y; 89 pushup(x); 90 } 91 } 92 inline void makeroot(int x){ 93 access(x); 94 splay(x); 95 pushr(x); 96 } 97 inline void split(int x,int y){ 98 makeroot(x); 99 access(y); 100 splay(y); 101 } 102 inline LL getans(Node x,LL lim){ 103 LL ans=0; 104 for(int i=k-1;i>=0;i--){ 105 if(x.l0&((LL)1<<i)) ans+=((LL)1<<i); 106 else if(lim>=((LL)1<<i)&&(x.l1&((LL)1<<i))) ans+=((LL)1<<i),lim-=((LL)1<<i); 107 } 108 return ans; 109 } 110 inline void link(int x,int y){ 111 makeroot(y); 112 fa[y]=x; 113 } 114 int main(){ 115 b[0].l0=b[0].r0=0,b[0].l1=b[0].r1=U; 116 n=read(),m=read(),k=read(); 117 for(int i=1;i<=n;i++){ 118 int x=read();LL y=read(); 119 calc(i,x,y); 120 } 121 for(int i=1;i<n;i++){ 122 int u=read(),v=read(); 123 link(u,v); 124 } 125 while(m--){ 126 int opt=read(),x=read(),y=read(); 127 LL z=read(); 128 if(opt==1){ 129 split(x,y); 130 printf("%llu\n",getans(b[y],z)); 131 } 132 else{ 133 splay(x); 134 calc(x,y,z); 135 pushup(x); 136 } 137 } 138 return 0; 139 }