【BZOJ3730】震波 - 动态点分治

题意:

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次操作。
$1\leq N,M\leq 100000$
$1\leq u,v,x\leq N$
$1\leq value[i],y\leq 10000$
$0\leq k\leq N-1$

Output

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

题解:

动态点分治裸题……

今天终于弄清楚动态点分治是啥玩意了……就是用数据结构爬点分树,大致感觉其实跟树链剖分差不多?(依稀记得我貌似还有个紫荆花之恋的大坑?!)

这题用RMQLCA+线段树随便维护一下就好了……

ps:我写的ST表求LCA+线段树跑了1600ms……卡常数の不能……orzlhx树状数组+神秘优化跑了543ms

代码:

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<cmath>
  6 #include<queue>
  7 #define inf 2147483647
  8 #define eps 1e-9
  9 using namespace std;
 10 typedef long long ll;
 11 struct edge{
 12     int v,next;
 13 }a[200001];
 14 struct node{
 15     int v,ls,rs;
 16 }t[20000001];
 17 int n,m,op,u,v,x,y,S,rt,ans=0,tot=0,tim=0,cnt=0,num[100001],f[100001],rt1[100001],rt2[100001],head[100001],mx[100001],dep[100001],siz[100001],dfn[100001],st[200001][18],lg[200001];
 18 bool used[100001];
 19 void add(int u,int v){
 20     a[++tot].v=v;
 21     a[tot].next=head[u];
 22     head[u]=tot;
 23 }
 24 void updata(int l,int r,int &u,int p,int x){
 25     if(!u)u=++cnt;
 26     t[u].v+=x;
 27     if(l==r)return;
 28     int mid=(l+r)/2;
 29     if(p<=mid)updata(l,mid,t[u].ls,p,x);
 30     else updata(mid+1,r,t[u].rs,p,x);
 31 }
 32 int query(int l,int r,int u,int p){
 33     if(!u)return 0;
 34     if(l==r)return t[u].v;
 35     int mid=(l+r)/2;
 36     if(p<=mid)return query(l,mid,t[u].ls,p);
 37     else return query(mid+1,r,t[u].rs,p)+t[t[u].ls].v;
 38 }
 39 int getdis(int u,int v){
 40     int l=dep[u]+dep[v],tmp;
 41     u=dfn[u];
 42     v=dfn[v];
 43     if(u>v)swap(u,v);
 44     tmp=lg[v-u+1];
 45     return l-min(st[u][tmp],st[v-(1<<tmp)+1][tmp])*2;
 46 }
 47 void dfs(int u,int fa,int dpt){
 48     dfn[u]=++tim;
 49     dep[u]=dpt;
 50     st[tim][0]=dep[u];
 51     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
 52         int v=a[tmp].v;
 53         if(v!=fa){
 54             dfs(v,u,dpt+1);
 55             st[++tim][0]=dep[u];
 56         }
 57     }
 58 }
 59 void getrt(int u,int fa){
 60     siz[u]=1;
 61     mx[u]=0;
 62     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
 63         int v=a[tmp].v;
 64         if(v!=fa&&!used[v]){
 65             getrt(v,u);
 66             siz[u]+=siz[v];
 67             mx[u]=max(mx[u],siz[v]);
 68         }
 69     }
 70     mx[u]=max(mx[u],S-mx[u]);
 71     if(mx[u]<mx[rt])rt=u;
 72 }
 73 void getn(int u,int fa,int ls){
 74     updata(0,n-1,rt1[ls],getdis(u,ls),num[u]);
 75     if(f[ls])updata(0,n-1,rt2[ls],getdis(u,f[ls]),num[u]);
 76     siz[u]=1;
 77     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
 78         int v=a[tmp].v;
 79         if(v!=fa&&!used[v]){
 80             getn(v,u,ls);
 81             siz[u]+=siz[v];
 82         }
 83     }
 84 }
 85 void divide(int u){
 86     getn(u,0,u);
 87     used[u]=true;
 88     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
 89         int v=a[tmp].v;
 90         if(!used[v]){
 91             S=siz[v];
 92             rt=0;
 93             getrt(v,0);
 94             f[rt]=u;
 95             divide(rt);
 96         }
 97     }
 98 }
 99 void LHX_AK_IOI(int u,int k){
100     for(int now=u;now;now=f[now]){
101         updata(0,n-1,rt1[now],getdis(u,now),k-num[u]);
102         if(f[now])updata(0,n-1,rt2[now],getdis(u,f[now]),k-num[u]);
103     }
104     num[u]=k;
105 }
106 int LHX_AK_NOI(int u,int k){
107     int ret=0;
108     for(int now=u;now;now=f[now]){
109         if(getdis(u,now)<=k)ret+=query(0,n-1,rt1[now],k-getdis(u,now));
110         if(f[now]&&getdis(u,f[now])<=k)ret-=query(0,n-1,rt2[now],k-getdis(u,f[now]));
111     }
112     return ret;
113 }
114 int main(){
115     memset(head,-1,sizeof(head));
116     scanf("%d%d",&n,&m);
117     for(int i=1;i<=n;i++)scanf("%d",&num[i]);
118     for(int i=1;i<n;i++){
119         scanf("%d%d",&u,&v);
120         add(u,v);
121         add(v,u);
122     }
123     dfs(1,0,1);
124     lg[0]=-1;
125     for(int i=1;i<=tim;i++)lg[i]=lg[i>>1]+1;
126     for(int i=1;(1<<i)<=tim;i++){
127         for(int j=1;j<=tim-(1<<i)+1;j++){
128             st[j][i]=min(st[j][i-1],st[j+(1<<i-1)][i-1]);
129         }
130     }
131     mx[rt=0]=inf;
132     S=n;
133     getrt(1,0);
134     divide(rt);
135     for(int i=1;i<=m;i++){
136         scanf("%d%d%d",&op,&x,&y);
137         x^=ans,y^=ans;
138         if(op==0){
139             ans=LHX_AK_NOI(x,y);
140             printf("%d\n",ans);
141         }else LHX_AK_IOI(x,y);
142     }
143     return 0;
144 }
posted @ 2018-10-26 21:23  DCDCBigBig  阅读(178)  评论(0编辑  收藏  举报