震波
写完捉迷藏之后这道题就很显然了。对于每一个点x维护其子树中每一个点到x的距离,并以此为下标动态开点建立线段树,线段树维护区间和,同时再求出其子树中每一个点到fa[x]的距离,并以此动态开点建立线段树。
关于线段树的点数,我感觉是要开nlog^2的,然而开不下,所以尽量开吧。
貌似bzoj上卡常...反正我没有被卡。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /************************************************************** 2 Problem: 3730 3 User: hyghb 4 Language: C++ 5 Result: Accepted 6 Time:13104 ms 7 Memory:185712 kb 8 ****************************************************************/ 9 10 #include<bits/stdc++.h> 11 #define mid ((l+r)>>1) 12 #define Rs t[o].ls 13 #define Ls t[o].rs 14 using namespace std; 15 const int inf=1e5+10; 16 int n,m,val[inf],last; 17 int tot,fi[inf],nxt[inf<<1],to[inf<<1]; 18 void link(int x,int y){ 19 to[++tot]=y;nxt[tot]=fi[x];fi[x]=tot; 20 } 21 int top[inf],Fa[inf],dep[inf],siz[inf],son[inf]; 22 void dfs1(int x){ 23 siz[x]=1; 24 for(int i=fi[x];i;i=nxt[i]){ 25 if(Fa[x]==to[i])continue; 26 Fa[to[i]]=x; 27 dep[to[i]]=dep[x]+1; 28 dfs1(to[i]); 29 siz[x]+=siz[to[i]]; 30 if(siz[to[i]]>siz[son[x]])son[x]=to[i]; 31 } 32 } 33 void dfs2(int x,int f){ 34 top[x]=f; 35 if(son[x])dfs2(son[x],f); 36 for(int i=fi[x];i;i=nxt[i]){ 37 if(top[to[i]])continue; 38 dfs2(to[i],to[i]); 39 } 40 } 41 int get_dis(int x,int y){ 42 int tmp=dep[x]+dep[y]; 43 while(top[x]!=top[y]){ 44 if(dep[top[x]]<dep[top[y]])swap(x,y); 45 x=Fa[top[x]]; 46 } 47 return tmp-min(dep[x],dep[y])*2+1;//防止0的情况 48 } 49 struct node{ 50 int ls,rs,val; 51 }t[inf*150];//不能再大了啊... 52 int segtree_size,maxr=100000,A[inf],B[inf];//A表示子树到当前点的的距离构成的线段树的根,B表示到当前点父亲距离构成线段树的根 53 void add(int l,int r,int &o,int x,int y){ 54 if(!o)o=++segtree_size; 55 t[o].val+=y; 56 if(l==r)return ; 57 if(x<=mid)add(l,mid,Ls,x,y); 58 else add(mid+1,r,Rs,x,y); 59 } 60 int sum(int l,int r,int o,int L,int R){ 61 if(!o)return 0; 62 if(l>=L&&r<=R)return t[o].val; 63 int ans=0; 64 if(mid>=L)ans+=sum(l,mid,Ls,L,R); 65 if(mid<R)ans+=sum(mid+1,r,Rs,L,R); 66 return ans; 67 } 68 int id,Min_size; 69 int fa[inf]; 70 bool vis[inf]; 71 void getsize(int x,int f){ 72 siz[x]=1; 73 for(int i=fi[x];i;i=nxt[i]){ 74 if(vis[to[i]] || to[i]==f)continue; 75 getsize(to[i],x); 76 siz[x]+=siz[to[i]]; 77 } 78 } 79 void getrt(int x,int f,int y){ 80 int tmp=-0x3fffffff; 81 for(int i=fi[x];i;i=nxt[i]){ 82 if(vis[to[i]] || to[i]==f)continue; 83 getrt(to[i],x,y); 84 tmp=max(tmp,siz[to[i]]); 85 } 86 tmp=max(tmp,y-siz[x]); 87 if(tmp<Min_size){ 88 Min_size=tmp; 89 id=x; 90 } 91 } 92 void dfs(int x,int f,int y){ 93 int dis1=get_dis(x,y),dis2=get_dis(x,fa[y]); 94 add(1,maxr,A[y],dis1,val[x]); 95 if(fa[y])add(1,maxr,B[y],dis2,val[x]); 96 for(int i=fi[x];i;i=nxt[i]){ 97 if(vis[to[i]] || to[i]==f)continue; 98 dfs(to[i],x,y); 99 } 100 } 101 void Div(int x,int f){ 102 getsize(x,0); 103 Min_size=0x3fffffff; 104 getrt(x,0,siz[x]); 105 int rt=id; 106 vis[rt]=1; 107 fa[rt]=f; 108 dfs(rt,0,rt); 109 for(int i=fi[rt];i;i=nxt[i]){ 110 if(vis[to[i]])continue; 111 Div(to[i],rt); 112 } 113 } 114 int main() 115 { 116 scanf("%d%d",&n,&m); 117 for(int i=1;i<=n;i++)scanf("%d",&val[i]); 118 for(int i=1;i<n;i++){ 119 int x,y; 120 scanf("%d%d",&x,&y); 121 link(x,y);link(y,x); 122 } 123 dfs1(1); 124 dfs2(1,1); 125 Div(1,0); 126 for(int i=1;i<=m;i++){ 127 int opt,x,y; 128 scanf("%d",&opt); 129 scanf("%d%d",&x,&y); 130 x^=last;y^=last; 131 if(!opt){ 132 y+=2; 133 last=0; 134 int now=x; 135 while(now){ 136 int dis=get_dis(now,x); 137 last+=sum(1,maxr,A[now],1,y-dis); 138 if(fa[now]){ 139 dis=get_dis(fa[now],x); 140 last-=sum(1,maxr,B[now],1,y-dis); 141 } 142 now=fa[now]; 143 } 144 printf("%d\n",last); 145 } 146 else { 147 int now=x; 148 while(now){ 149 add(1,maxr,A[now],get_dis(now,x),y-val[x]); 150 if(fa[now])add(1,maxr,B[now],get_dis(fa[now],x),y-val[x]); 151 now=fa[now]; 152 } 153 val[x]=y; 154 } 155 } 156 return 0; 157 } 158