bzoj3730 [震波][动态树分治+线段树+LCA]

震波

Time Limit: 15 Sec  Memory Limit: 256 MB
Submit: 1573  Solved: 358
[Submit][Status][Discuss]

Description

在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]。
不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
接下来你需要在线处理M次操作:
0 x k 表示发生了一次地震,震中城市为x,影响范围为k,所有与x距离不超过k的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和。
1 x y 表示第x个城市的价值变成了y。
为了体现程序的在线性,操作中的x、y、k都需要异或你程序上一次的输出来解密,如果之前没有输出,则默认上一次的输出为0。

Input

第一行包含两个正整数N和M。
第二行包含N个正整数,第i个数表示value[i]。
接下来N-1行,每行包含两个正整数u、v,表示u和v之间有一条无向边。
接下来M行,每行包含三个数,表示M次操作。

Output

包含若干行,对于每个询问输出一行一个正整数表示答案。

Sample Input

8 1
1 10 100 1000 10000 100000 1000000 10000000
1 2
1 3
2 4
2 5
3 6
3 7
3 8
0 3 1

Sample Output

11100101

HINT

 

1<=N,M<=100000

1<=u,v,x<=N

1<=value[i],y<=10000

0<=k<=N-1

 

Source

题解:先建立点分树

ra :表示该节点点分树子树内到其距离为某值的所有节点的权值和

rb:示该节点点分树子树内到其父亲节点距离为某值的所有节点的权值和

 

另一个问题:如何快速求出两点间距离?使用RMQLCA,预处理后 O(1) 查询LCA深度即可。

 

然后就是类似是容斥吧,维护即可。

修改的话就是计算delta,来解决。

每次不管怎么样,log层,每层的线段树上解决,

n log n是极限,所以可以认为是 n log^2n的时间复杂度。

 

然后就可以解决了,线段树的基本操作吧。

  1 #include<cstring>
  2 #include<cmath>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<cstdio>
  6 
  7 #define N 100007
  8 using namespace std;
  9 inline int read()
 10 {
 11     int x=0,f=1;char ch=getchar();
 12     while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
 13     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
 14     return x*f;
 15 }
 16 
 17 int n,m,lastans,S,tot,xj;
 18 int cnt,hed[N],rea[N*2],nxt[N*2];
 19 int pos[N],mn[20][N*2],dep[N];
 20 int value[N],vis[N],sz[N],fa[N],ra[N],rb[N],rt,f[N],Log[N*2];
 21 int ls[N*200],rs[N*200],sum[N*200],tp;
 22 
 23 void add(int u,int v)
 24 {
 25     nxt[++cnt]=hed[u];
 26     hed[u]=cnt;
 27     rea[cnt]=v;
 28 }
 29 void get_root(int u,int fa)
 30 {
 31     sz[u]=1,f[u]=0;
 32     for (int i=hed[u];i!=-1;i=nxt[i])
 33     {
 34         int v=rea[i];
 35         if (vis[v]||v==fa)continue;
 36         get_root(v,u),sz[u]+=sz[v],f[u]=max(f[u],sz[v]);
 37     }
 38     f[u]=max(f[u],S-sz[u]);
 39     if (f[u]<f[rt])rt=u;
 40 }
 41 inline int dis(int x,int y)
 42 {
 43     int t=dep[x]+dep[y],k;
 44     x=pos[x],y=pos[y];
 45     if (x>y)swap(x,y);
 46     k=Log[y-x+1];
 47     return t-(min(mn[k][x],mn[k][y-(1<<k)+1])<<1);
 48 }
 49 void update(int p,int a,int l,int r,int &x)
 50 {
 51     if (!x)x=++xj;
 52     sum[x]+=a;
 53     if (l==r)return;
 54     int mid=(l+r)>>1;
 55     if (p<=mid)update(p,a,l,mid,ls[x]);
 56     else update(p,a,mid+1,r,rs[x]);
 57 }
 58 int query(int p,int l,int r,int x)
 59 {
 60     if (!x) return 0;
 61     if (l==r) return sum[x];
 62     int mid=(l+r)>>1;
 63     if (p<=mid)return query(p,l,mid,ls[x]);
 64     else return query(p,mid+1,r,rs[x])+sum[ls[x]];
 65 }
 66 void calc(int u,int par,int p)
 67 {
 68     update(dis(u,p),value[u],0,n-1,ra[p]);
 69     if (fa[p])update(dis(u,fa[p]),value[u],0,n-1,rb[p]);
 70     for (int i=hed[u];i!=-1;i=nxt[i])
 71     {
 72         int v=rea[i];
 73         if (vis[v]||v==par) continue;
 74         calc(v,u,p);
 75     }
 76 }
 77 void divide(int u)
 78 {
 79     calc(u,0,u),vis[u]=1;int yS=S;
 80     for (int i=hed[u];i!=-1;i=nxt[i])
 81     {
 82         int v=rea[i];
 83         if (vis[v])continue;
 84         rt=0;
 85         if (sz[v]>sz[u])S=yS-sz[u];
 86         else S=sz[v];
 87         get_root(v,0),fa[rt]=u;
 88         divide(rt);
 89     }
 90 }
 91 inline void modify(int x,int y)
 92 {
 93     for (int i=x;i!=0;i=fa[i])
 94     {
 95         update(dis(x,i),y-value[x],0,n-1,ra[i]);
 96         if (fa[i])update(dis(x,fa[i]),y-value[x],0,n-1,rb[i]);
 97     }
 98     value[x]=y;
 99 }
100 inline int solve(int x,int p)
101 {
102     int res=0;
103     for (int i=x;i!=0;i=fa[i])
104     {
105         if (dis(x,i)<=p)res+=query(p-dis(x,i),0,n-1,ra[i]);
106         if (fa[i]&&dis(x,fa[i])<=p)res-=query(p-dis(x,fa[i]),0,n-1,rb[i]);
107     }
108     return res;
109 }
110 void dfs(int u,int par)
111 {
112     pos[u]=++tot,mn[0][tot]=dep[u];
113     for (int i=hed[u];i!=-1;i=nxt[i])
114     {
115         int v=rea[i];
116         if (v==par) continue;
117         dep[v]=dep[u]+1,dfs(v,u),mn[0][++tot]=dep[u];
118     }
119 }
120 int main()
121 {
122     memset(hed,-1,sizeof(hed));
123 
124     n=read(),m=read();
125     for (int i=1;i<=n;i++)
126         value[i]=read();
127     for (int i=1;i<n;i++)
128     {
129         int x=read(),y=read();
130         add(x,y),add(y,x);
131     }
132     dfs(1,0);
133     for (int i=2;i<=tot;i++)Log[i]=Log[i>>1]+1;
134     for (int i=1;(1<<i)<=tot;i++)
135         for (int j=1;j<=tot-(1<<i)+1;j++)
136             mn[i][j]=min(mn[i-1][j],mn[i-1][j+(1<<(i-1))]);
137     f[0]=1<<30,S=n;
138     get_root(1,0),divide(rt);
139     while(m--)
140     {
141         int flag=read(),x=read()^lastans,y=read()^lastans;
142         if (flag)modify(x,y);
143         else printf("%d\n",lastans=solve(x,y));
144     }
145 }

 

posted @ 2018-01-10 11:27  Kaiser-  阅读(192)  评论(0编辑  收藏  举报