[BZOJ4372][动态树分治(点分树)][动态开点线段树]烁烁的游戏
2017-02-28 18:23
537 查看
题意
给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:Q x:询问x的点权
M x d w:将树上与节点x距离不超过d的节点的点权均加上w
dfs出点分树
每个重心要记录这个重心以下的子点分树的修改信息,可以用区间覆盖单店查询的线段树维护,因为会有重复的部分,每个重心还要再开一棵线段树记录重复的部分
#include <cstdio> #include <iostream> #include <algorithm> #define N 100010 using namespace std; int n,m,cnt,u,v,mn,isz,id; int G ,vis ,dpt ,p ,rt ,rt1 ; int fa [25]; char op; struct edge{ int t,nx; }E[N<<1]; struct sgm{ int l,r,ls,rs,tot,flg; }T[N*150]; inline void Read(int &x){ char c=getchar();x=0; int f=1; for(;c>57||c<48;c=getchar())if(c=='-')f=-1; for(;c>=48&&c<=57;x=x*10+c-48,c=getchar()); x*=f; } inline void Insert(int u,int v){ E[++cnt].t=v; E[cnt].nx=G[u]; G[u]=cnt; E[++cnt].t=u; E[cnt].nx=G[v]; G[v]=cnt; } int get_size(int x,int f){ int sz=1; for(int i=G[x];i;i=E[i].nx) if(E[i].t!=f&&!vis[E[i].t]) sz+=get_size(E[i].t,x); return sz; } int get_root(int x,int f,int &rt){ int sz=1,maxx=0; for(int i=G[x];i;i=E[i].nx) if(E[i].t!=f&&!vis[E[i].t]){ int k=get_root(E[i].t,x,rt); if(k>maxx) maxx=k; sz+=k; } if(isz-sz>maxx) maxx=isz-sz; if(maxx<mn) mn=maxx,rt=x; return sz; } int dfs(int x){ isz=get_size(x,0); mn=1<<30; int rt; get_root(x,0,rt); vis[rt]=1; for(int i=G[rt];i;i=E[i].nx) if(!vis[E[i].t]) p[dfs(E[i].t)]=rt; return rt; } void explore(int x,int f){ dpt[x]=dpt[f]+1; fa[x][0]=f; for(int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for(int i=G[x];i;i=E[i].nx) if(E[i].t!=f) explore(E[i].t,x); } inline int LCA(int x,int y){ if(dpt[x]<dpt[y]) return LCA(y,x); for(int i=20;~i;i--) if(dpt[fa[x][i]]>=dpt[y]) x=fa[x][i]; if(x==y) return x; for(int i=20;~i;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } inline int dis(int x,int y){ return dpt[x]+dpt[y]-2*dpt[LCA(x,y)]; } int query(int g,int x){ if(!g) return 0; if(T[g].l==T[g].r) return T[g].tot; int mid=T[g].l+T[g].r>>1; if(x<=mid) return query(T[g].ls,x)+T[g].tot; else return query(T[g].rs,x)+T[g].tot; } inline int query(int x){ int dist=0,r=query(rt[x],dist); for(int i=x;p[i];i=p[i]){ dist=dis(p[i],x); r+=query(rt[p[i]],dist)+query(rt1[i],dist); } return r; } void add(int &g,int L,int R,int l,int r,int v){ if(!g){ g=++id,T[g].l=L,T[g].r=R; T[g].flg=T[g].tot=0; } if(L==l&&r==R){ T[g].tot+=v; return ; } int mid=L+R>>1; if(r<=mid) add(T[g].ls,L,mid,l,r,v); else if(l>mid) add(T[g].rs,mid+1,R,l,r,v); else add(T[g].ls,L,mid,l,mid,v),add(T[g].rs,mid+1,R,mid+1,r,v); } inline void add(int x,int d,int v){ int dist; add(rt[x],0,n,0,d,v); for(int i=x;p[i];i=p[i]){ dist=dis(p[i],x); if(dist>d) continue; add(rt1[i],0,n,0,d-dist,-v); add(rt[p[i]],0,n,0,d-dist,v); } } int main(){ Read(n); Read(m); for(int i=1;i<n;i++) Read(u),Read(v),Insert(u,v); explore(1,0); dfs(1); for(int i=1;i<=m;i++){ while((op=getchar())!='Q'&&op!='M'); if(op=='Q'){ int x; Read(x); printf("%d\n",query(x)); } else{ int x,d,v; Read(x); Read(d); Read(v); add(x,d,v); } } return 0; }
相关文章推荐
- bzoj 4372: 烁烁的游戏 (动态点分治+线段树+LCA)
- 【BZOJ4372】烁烁的游戏(动态点分治)
- 【BZOJ4372】烁烁的游戏(动态点分治)
- [BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA]
- BZOJ 3730: 震波 动态树分治 线段树 lca
- bzoj3924 [Zjoi2015]幻想乡战略游戏(动态点分治)
- BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)
- bzoj3295[Cqoi2011]动态逆序对(cdq分治||可持久化线段树)
- [BZOJ3924][ZJOI2015]幻想乡战略游戏(动态点分治)
- [BZOJ]4372: 烁烁的游戏
- 【BZOJ3924】幻想乡战略游戏(动态点分治)
- [点分树] BZOJ 4372: 烁烁的游戏
- [BZOJ3924][Zjoi2015]幻想乡战略游戏(动态点分治)
- 【BZOJ4372】烁烁的游戏 动态树分治
- 【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治
- 【bzoj4372】烁烁的游戏 动态点分治+线段树
- [BZOJ4372]烁烁的游戏
- [bzoj4372] 烁烁的游戏 [动态点分治+线段树+容斥原理]
- [ZJOI2015][bzoj3924] 幻想乡战略游戏 [动态点分治]
- BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)