BZOJ 3730 震波
2018-01-26 09:44
337 查看
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 11 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
11100101HINT
1<=N,M<=1000001<=u,v,x<=N
1<=value[i],y<=10000
0<=k<=N-1
[b]先构造出一个动态点分树[/b]
[b]查询时,首先就考虑在当前块内和x距离为k的[/b]
[b]然后还要考虑其他含有x的树根,所以顺着点分树[/b]
[b]然后向上走到i,距离为d[/b]
[b]查询距离树根为k-d的点权和[/b]
[b]这些用线段树以距离为下标实现,每一个根动态开点[/b]
[b]但是还要减去原来子树的,因为不可能走重复的路径[/b]
[b]所以再维护一颗线段树,在往上跳时记录x传递到x上一个根的答案[/b]
[b]查询时减去x传递到上一根的答案就行了[/b]
[b]此题玄学卡常,可以换一种点分写法,这样可以省去get_size操作,快了不少[/b]
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define MAX 120000 struct Node { int next,to; }edge[MAX<<1]; int num,head[MAX]; int dep[MAX],fa[MAX],pos,size[MAX],minsize,root; int FA[MAX],son[MAX],top[MAX],Size; int sum[MAX*150]; int ch[MAX*150][2],RT[MAX<<1],n,m; int ans,val[MAX]; bool vis[MAX]; inline int gi() { int x=0,flag=1; char ch=getchar(); while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=getchar(); } while (ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); } return x*flag; } inline void add(int u,int v) { num++; edge[num].next=head[u]; head[u]=num; edge[num].to=v; } void dfs1(int x,int pa) { size[x]=1; dep[x]=dep[pa]+1; for (int i=head[x];i;i=edge[i].next) { int v=edge[i].to; if (v==pa) continue; fa[v]=x; dfs1(v,x); size[x]+=size[v]; if (size[son[x]]<size[v]) son[x]=v; } } void dfs2(int x,int tp) { top[x]=tp; if (son[x]) dfs2(son[x],tp); for (int i=head[x];i;i=edge[i].next) { int v=edge[i].to; if (v==fa[x]||v==son[x]) continue; dfs2(v,v); } } int lca(int x,int y) { while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); x=fa[top[x]]; } if (dep[x]<dep[y]) return x; return y; } int dis(int x,int y) { return dep[x]+dep[y]-(dep[lca(x,y)]<<1); } void get_root(int x,int pa) { size[x]=1; int ret=0; for (int i=head[x];i;i=edge[i].next) { int v=edge[i].to; if (v==pa||vis[v]) continue; get_root(v,x); size[x]+=size[v]; if (size[v]>ret) ret=size[v]; } if (Size-size[x]>ret) ret=Size-size[x]; if (ret<minsize) minsize=ret,root=x; } void solve(int x,int pa) { vis[x]=1; FA[x]=pa; for (int i=head[x];i;i=edge[i].next) { int v=edge[i].to; if (vis[v]) continue; minsize=n;Size=size[v]; get_root(v,x); solve(root,x); } } void update(int &rt,int l,int r,int x,int k) { if (!rt) rt=++pos; sum[rt]+=k; if (l==r) return; int mid=(l+r)>>1; if (x<=mid) update(ch[rt][0],l,mid,x,k); else update(ch[rt][1],mid+1,r,x,k); } int query(int rt,int l,int r,int L,int R) { if (!rt) return 0; if (l>=L&&r<=R) return sum[rt]; int mid=(l+r)>>1; int s=0; if (L<=mid) s+=query(ch[rt][0],l,mid,L,R); if (R>mid) s+=query(ch[rt][1],mid+1,r,L,R); return s; } void change(int u,int w) { update(RT[u],0,n,0,w); for (int i=u;FA[i];i=FA[i]) { int d=dis(u,FA[i]); update(RT[FA[i]],0,n,d,w); update(RT[i+n],0,n,d,w); } } void ask(int u,int k) { ans+=query(RT[u],0,n,0,k); for (int i=u;FA[i];i=FA[i]) { int d=dis(u,FA[i]); if (d>k) continue; ans+=query(RT[FA[i]],0,n,0,k-d); ans-=query(RT[i+n],0,n,0,k-d); } } int main() {int u,v; cin>>n>>m; for (int i=1;i<=n;i++) val[i]=gi(); for (int i=1;i<=n-1;i++) { u=gi();v=gi(); add(u,v);add(v,u); } dfs1(1,0); dfs2(1,1); minsize=Size=n; get_root(1,0); solve(root,0); for (int i=1;i<=n;i++) change(i,val[i]); ans=0; for (int i=1;i<=m;i++) { int opt=gi(); int x=gi(),y=gi(); if (opt==0) { x^=ans;y^=ans; ans=0; ask(x,y); printf("%d\n",ans); } else { x^=ans;y^=ans; change(x,y-val[x]); val[x]=y; } } return 0; }
相关文章推荐
- 【BZOJ3730】震波 动态树分治+线段树
- bzoj 3730: 震波 (动态点分治)
- Bzoj3730 震波
- BZOJ 3730 震波 - 点分树+线段树+容斥
- [点分树 树状数组] BZOJ 3730 震波
- 【BZOJ-3730】震波 动态点分治 + 树状数组
- BZOJ 3730 震波
- [bzoj3730][点分治]震波
- 【bzoj3730】震波【动态树分治】
- bzoj 3730: 震波 (点分树+线段树)
- Bzoj3730: 震波
- BZOJ 3730: 震波 动态树分治 线段树 lca
- 【BZOJ3730】震波(动态点分治)
- [BZOJ]3730 震波 动态点分治&树状数组
- 【BZOJ3730】震波(动态点分治)
- BZOJ3730: 震波
- [BZOJ3730]震波(动态点分治)
- [动态点分治] BZOJ3730: 震波
- [BZOJ3730]震波-动态点分治
- [BZOJ3730][震波][动态树分治+线段树+LCA]