[bzoj3730] 震波

  点分治+线段树。。

  对于每个重心,以点到重心的距离建权值线段树,维护点权总和。

  修改就在那个点所属的logn棵线段树里改。

  但显然查询的时候要考虑去重的问题...

  对于当前层的重心,记录一下它在  上一层的重心的哪个儿子  的子树里,等一下查询到上一层的时候要把这部分的去掉(对应子树内的点应该是给这一层的重心算的)。

  去掉的话。。就对子树新开一颗线段树,权值是子树内的点到上一层重心的距离。。。累加的时候用这一层的答案减去子树内的答案。

  查询的时候,在查询的点所属的logn个重心的线段树里查询,去重如上文。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ll long long
 6 using namespace std;
 7 const int maxn=100023,inf=1002333333,mxnode=10000233;
 8 struct zs{
 9     int too,pre;
10 }e[maxn<<1];int tot,last[maxn];
11 int root[maxn<<1],lc[mxnode],rc[mxnode],sm[mxnode],tt;
12 int sz[maxn],mx[maxn],dis[maxn],val[maxn],p[maxn],mxdep[maxn],num,poi,rt;
13 int f[30][maxn],dist[30][maxn];
14 bool del[maxn];
15 int i,j,k,n,m;
16   
17 int ra;char rx;
18 inline int read(){
19     rx=getchar(),ra=0;
20     while(rx<'0'||rx>'9')rx=getchar();
21     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
22 }
23   
24   
25 void add(int &x,int a,int b,int pos,int val){
26     if(!x)x=++tt;
27     sm[x]+=val;
28     if(a==b)return;
29     int mid=a+b>>1;
30     if(pos<=mid)add(lc[x],a,mid,pos,val);else add(rc[x],mid+1,b,pos,val);
31 }
32 int que(int x,int a,int b,int K){
33     if(!x||K>=b)return sm[x];
34     int mid=a+b>>1;
35     if(K>mid) return sm[lc[x]]+que(rc[x],mid+1,b,K);
36     else return que(lc[x],a,mid,K);
37 }
38   
39   
40 void getrt(int x,int fa){
41     sz[x]=1;
42     for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa&&!del[e[i].too])
43         getrt(e[i].too,x),sz[x]+=sz[e[i].too];
44     mx[x]=max(sz[x]-1,poi-sz[x]+1);
45     if(mx[x]<mx[rt])rt=x;
46 }
47 void getpoi(int rt,int x,int fa){
48     add(root[rt],0,n,dis[x],val[x]);
49     for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa&&!del[e[i].too])
50         p[++num]=e[i].too,dis[e[i].too]=dis[x]+1,getpoi(rt,e[i].too,x);
51 }
52   
53 void work(int dep,int x,int next,int precg){
54     int i,cg;//cg:center of gravity
55     getrt(x,rt=0),cg=rt;
56     if(next!=0)dis[next]=1,num=0,getpoi(cg+n,next,0);
57      
58     del[cg]=1,mxdep[cg]=dep;
59     dis[cg]=0,p[num=1]=cg,getpoi(cg,cg,0);
60     for(i=1;i<=num;i++)dist[dep][p[i]]=dis[p[i]],f[dep][p[i]]=cg;
61       
62     for(i=last[cg];i;i=e[i].pre)if(!del[e[i].too])
63         poi=sz[e[i].too],work(dep+1,e[i].too,e[i].too,cg);
64 }
65 inline int query(int x,int K){
66     int i,ans=que(root[x],0,n,K);
67     for(i=mxdep[x]-1;i;i--)
68         ans+=que(root[f[i][x]],0,n,K-dist[i][x])-que(root[f[i+1][x]+n],0,n,K-dist[i][x]);
69     return ans;
70 }
71 inline void change(int x,int v){
72     int delta=v-val[x],i,pre=x;val[x]=v;
73     add(root[x],0,n,0,delta);
74     for(i=mxdep[x]-1;i;i--)
75         add(root[f[i][x]],0,n,dist[i][x],delta),add(root[f[i+1][x]+n],0,n,dist[i][x],delta);
76 }
77 inline void insert(int a,int b){
78     e[++tot].too=b,e[tot].pre=last[a],last[a]=tot;
79     e[++tot].too=a,e[tot].pre=last[b],last[b]=tot;
80 }
81   
82 int main(){
83     mx[0]=inf;
84     n=read(),m=read();
85     for(i=1;i<=n;i++)val[i]=read();
86     for(i=1;i<n;i++)insert(read(),read());
87     poi=n,work(1,1,0,0);
88      
89     int id,la=0;
90     while(m--){
91         id=read(),j=read(),k=read();
92         j^=la,k^=la;
93         if(id==0)printf("%d\n",la=query(j,k));
94         else change(j,k);
95     }
96     return 0;
97 }
View Code

 卡着时限过去的TAT

posted @ 2016-04-19 13:22  czllgzmzl  阅读(306)  评论(0编辑  收藏  举报