[bzoj3730]震波

建立点分树(以下除距离都指在点分树上的,距离可以每一次倍增计算lca)
对于每一个点,维护子树内所有点到这个点的距离的线段树和子树内所有点到这个点父亲的距离的的线段树,然后对于查询和修改暴力修改或询问每一个祖先即可(点分数树高logn)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 100005
  4 #define mid (l+r>>1)
  5 struct ji{
  6     int nex,to;
  7 }edge[N<<1];
  8 int E,n,m,p,x,y,ans,a[N],v[N],vis[N],head[N],sh[N],f[N][21];
  9 int V,r,ma[N],sz[N],fa[N],r1[N],r2[N],sum[N<<6],ls[N<<6],rs[N<<6];
 10 void add(int x,int y){
 11     edge[E].nex=head[x];
 12     edge[E].to=y;
 13     head[x]=E++;
 14 }
 15 int lca(int x,int y){
 16     if (sh[x]<sh[y])swap(x,y);
 17     for(int i=20;i>=0;i--)
 18         if (sh[x]-(1<<i)>=sh[y])x=f[x][i];
 19     if (x==y)return x;
 20     for(int i=20;i>=0;i--)
 21         if (f[x][i]!=f[y][i]){
 22             x=f[x][i];
 23             y=f[y][i];
 24         }
 25     return f[x][0];
 26 }
 27 int dis(int x,int y){
 28     return sh[x]+sh[y]-2*sh[lca(x,y)];
 29 }
 30 void dfs(int k,int fa,int s){
 31     sh[k]=s;
 32     f[k][0]=fa;
 33     for(int i=1;i<=20;i++)f[k][i]=f[f[k][i-1]][i-1];
 34     for(int i=head[k];i!=-1;i=edge[i].nex)
 35         if (edge[i].to!=fa)dfs(edge[i].to,k,s+1);
 36 }
 37 void update(int &k,int l,int r,int x,int y){
 38     if (!k)k=++V;
 39     sum[k]+=y;
 40     if (l==r)return;
 41     if (x<=mid)update(ls[k],l,mid,x,y);
 42     else update(rs[k],mid+1,r,x,y);
 43 }
 44 int query(int k,int l,int r,int x,int y){
 45     if ((!k)||(l>y)||(x>r))return 0;
 46     if ((x<=l)&&(r<=y))return sum[k];
 47     return query(ls[k],l,mid,x,y)+query(rs[k],mid+1,r,x,y);
 48 }
 49 void tj(int k,int fa){
 50     v[++v[0]]=k;
 51     for(int i=head[k];i!=-1;i=edge[i].nex){
 52         int v=edge[i].to;
 53         if ((v!=fa)&&(!vis[v]))tj(v,k);
 54     }
 55 }
 56 void find(int k,int fa,int s){
 57     sz[k]=1;
 58     ma[k]=0;
 59     for(int i=head[k];i!=-1;i=edge[i].nex){
 60         int v=edge[i].to;
 61         if ((v==fa)||(vis[v]))continue;
 62         find(v,k,s);
 63         ma[k]=max(ma[k],sz[v]);
 64         sz[k]+=sz[v];
 65     }
 66     if (max(s-sz[k],ma[k])<=s/2)r=k;
 67 }
 68 int dfs(int k,int f){
 69     fa[k]=f;
 70     v[0]=0;
 71     tj(k,0);
 72     find(k,0,v[0]);
 73     vis[r]=1;
 74     for(int i=1;i<=v[0];i++)update(r1[r],0,n,dis(r,v[i]),a[v[i]]);
 75     if (f)for(int i=1;i<=v[0];i++)update(r2[r],0,n,dis(f,v[i]),a[v[i]]);
 76     for(int i=head[r];i!=-1;i=edge[i].nex)
 77         if (!vis[edge[i].to])dfs(edge[i].to,k);
 78 }
 79 int main(){
 80     scanf("%d%d",&n,&m);
 81     memset(head,-1,sizeof(head));
 82     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
 83     for(int i=1;i<n;i++){
 84         scanf("%d%d",&x,&y);
 85         add(x,y);
 86         add(y,x);
 87     }
 88     dfs(1,0,0);
 89     dfs(1,0);
 90     for(int i=1;i<=m;i++){
 91         scanf("%d%d%d",&p,&x,&y);
 92         if (!p){
 93             ans=query(r1[x],0,n,0,y);
 94             while (fa[x]){
 95                 y-=dis(x,fa[x]);
 96                 ans-=query(r2[x],0,n,0,y);
 97                 x=fa[x];
 98                 ans+=query(r1[x],0,n,0,y);
 99             }
100             printf("%d\n",ans);
101         }
102         if (p){
103             y-=a[x];
104             a[x]+=y;
105             for(int i=x;i;i=fa[i])update(r1[i],0,n,dis(i,x),y);
106             for(int i=x;fa[i];i=fa[i])update(r2[i],0,n,dis(fa[i],x),y);
107         }
108     }
109 }
View Code

 

posted @ 2019-10-07 06:17  PYWBKTDA  阅读(201)  评论(0编辑  收藏  举报