BZOJ -3730(动态点分治)
题目:在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]。
不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
接下来你需要在线处理M次操作:
0 x k 表示发生了一次地震,震中城市为x,影响范围为k,所有与x距离不超过k的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和。
1 x y 表示第x个城市的价值变成了y。
为了体现程序的在线性,操作中的x、y、k都需要异或你程序上一次的输出来解密,如果之前没有输出,则默认上一次的输出为0。
思路:点分树,动态维护一个重心的信息。 这里维护的是点到其他点的某距离下的权值和。 注意处理重复信息。
时间卡得有点紧,ST表求LCA,没树剖快。。。居然?
线段树没树状数组快,这个可以理解,关键是在于怎么开点,不会炸空间--------把空间和点分树的对应起来O(NlogN)就可以了。
(T了很多次,也改(抄)了不少写法,日后再来补。
#include<bits/stdc++.h> using namespace std; #define ll long long #define RG register #define MAX 111111 inline int read() { RG int x=0,t=1;RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } int n,m,V[MAX]; struct Line{int v,next;}e[MAX<<1]; int h[MAX],cnt=1; inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;} /********************************************************************/ /*int size[MAX],dfn[MAX],top[MAX],dep[MAX],fa[MAX],tim,hson[MAX]; void dfs1(int u,int ff) { fa[u]=ff;size[u]=1;dep[u]=dep[ff]+1; for(int i=h[u];i;i=e[i].next) { int v=e[i].v;if(v==ff)continue; dfs1(v,u);size[u]+=size[v]; if(size[v]>size[hson[u]])hson[u]=v; } } void dfs2(int u,int tp) { top[u]=tp; if(hson[u])dfs2(hson[u],tp); for(int i=h[u];i;i=e[i].next) if(e[i].v!=fa[u]&&e[i].v!=hson[u]) dfs2(e[i].v,e[i].v); } int LCA(int u,int v) { while(top[u]^top[v])dep[top[u]]<dep[top[v]]?v=fa[top[v]]:u=fa[top[u]]; return dep[u]<dep[v]?u:v; } int Dis(int u,int v){return dep[u]+dep[v]-2*dep[LCA(u,v)];}*/ bool vis[MAX]; int ver[MAX<<1],first[MAX<<1],dept[MAX<<1],Tot; int dp[MAX<<1][21],dep[MAX<<1]; void dfs(int u ,int d) { vis[u]=true; ver[++Tot] = u; first[u] = Tot; dept[Tot] = d; dep[u]=d; for(int i=h[u];i;i=e[i].next) if( !vis[e[i].v] ) { dfs(e[i].v,d+1); ver[++Tot] = u; dept[Tot] = d; } } void ST(int N) { for(int i=1;i<=N;i++) dp[i][0] = i; for(int j=1;(1<<j)<=N;j++) { for(int i=1;i+(1<<j)-1<=N;i++) { int a = dp[i][j-1] , b = dp[i+(1<<(j-1))][j-1]; dp[i][j] = dept[a]<dept[b]?a:b; } } } int lg2[MAX<<1]; int RMQ(int l,int r) { int k=0; //while((1<<(k+1))<=r-l+1) k++; k=lg2[r-l+1]; int a=dp[l][k],b=dp[r-(1<<k)+1][k]; return dept[a]<dept[b]?a:b; } int LCA(int u ,int v) { int x = first[u] , y = first[v]; int res; if(x<=y) res = RMQ(x,y); else res=RMQ(y,x); //cout<<u<<" "<<v<<" : "<<ver[res]<<endl; return ver[res]; } int Dis(int u,int v) { return dep[u]+dep[v]-(dep[LCA(u,v)]<<1); } namespace BIT{ typedef vector<int> vec; struct BIT{ vec tree; int n; inline void init(int size) {tree.resize(size+2); n=size+1;} inline int lowbit(int x) {return x&-x;} inline void Modify(int x,int d) {if (x<=0) return; for (int i=x; i<=n; i+=lowbit(i)) tree[i]+=d;} inline int Query(int x) {int re=0; if (x>n) x=n; for (int i=x; i>0; i-=lowbit(i)) re+=tree[i]; return re;} }G[MAX<<1]; }using namespace BIT; int Fa[MAX],Size,root,mx,size[MAX]; void Getroot(int u,int ff) { size[u]=1;int ret=0; for(int i=h[u];i;i=e[i].next) { int v=e[i].v;if(v==ff||vis[v])continue; Getroot(v,u);size[u]+=size[v]; ret=max(ret,size[v]); } ret=max(ret,Size-size[u]); if(ret<mx)mx=ret,root=u; } void DFS(int u,int ff) { vis[u]=true;Fa[u]=ff; for(int i=h[u];i;i=e[i].next) { int v=e[i].v;if(vis[v])continue; mx=Size=size[v]; Getroot(v,u); G[root].init(Size); G[root+n].init(Size); DFS(root,u); } } void Modify(int x,int w) { G[x].Modify(1,w); for(int i=x;Fa[i];i=Fa[i]) { int dis=Dis(x,Fa[i]); G[Fa[i]].Modify(dis+1,w); G[i+n].Modify(dis+1,w); } } int Query(int x,int K) { int ret=G[x].Query(K+1); for(int i=x;Fa[i];i=Fa[i]) { int dis=Dis(x,Fa[i]);if(dis>K)continue; //ret+=Query(rt[Fa[i]],0,n,0,K-dis); //ret-=Query(rt[i+n],0,n,0,K-dis); ret+=G[Fa[i]].Query(K-dis+1); ret-=G[i+n].Query(K-dis+1); } return ret; } /********************************************************************/ int main() { n=read();m=read(); for(int i=1;i<=n;++i)V[i]=read(); for(int i=1;i<n;++i) { int u=read(),v=read(); Add(u,v);Add(v,u); } /*dfs1(1,0);dfs2(1,1);*/ dfs(1,0); ST(Tot); lg2[0]=-1; for(int i=1;i<=Tot;i++) lg2[i]=lg2[i>>1]+1; for(int i=1;i<=n;i++) vis[i]=0; Size=mx=n; Getroot(1,0); G[root].init(n); G[root+n].init(n);DFS(root,0); for(int i=1;i<=n;++i) Modify(i,V[i]); int ans=0; while(m--) { int opt=read(),x=read()^ans,y=read()^ans; if(opt==0)printf("%d\n",ans=Query(x,y)); else Modify(x,y-V[x]),V[x]=y; } return 0; }
It is your time to fight!