您的位置:首页 > 其它

[bzoj4372]烁烁的游戏

2017-06-05 16:36 267 查看
来自FallDream的博客,未经允许,请勿转载,谢谢。

背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠。
题意:
给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠。
烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠。皮皮鼠会被烁烁吸引,所以会一直待在节点上不动。
烁烁很好奇,在当前时刻,节点u有多少个他的好朋友---皮皮鼠。
大意:
给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:
Q x:询问x的点权。
M x d w:将树上与节点x距离不超过d的节点的点权均加上w。

n,m<=10^5 wi<=10^4

让离树上一个点距离小等于d的点的权值加上一个数,这个是可以点分来做的,每次分治都统计一个子树对其它子树的答案的影响。

这道题就动态点分呗。

先建出分治结构,然后每个分治的子结构开一个线段树维护不同深度的答案。

为了去重,每个分治结构的每个子树还要开一个线段树,表示在这个子树内要去掉的答案。

询问和修改直接从分治结构最底层向上爬,修改或者查询线段树上的值就行了。

复杂度nlog^2n

#include<iostream>
#include<cstdio>
#define INF 2000000000
#define MN 100000
#define MD 18
using namespace std;
inline int read()
{
int x = 0 , f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
return x * f;
}
bool b[MN+5];
int n,m,head[MN+5],cnt=0,mn,rt,tot,dep[MD+5][MN+5],bel[MD+5][MN+5];
int size[MN+5],mx[MN+5],Fa[MD+5][MN+5],Mxdp[MN+5];
struct edge{int to,next;}e[MN*2+5];
struct Tree{int l,r,x;}T[20000000];
inline void ins(int f,int t)
{
e[++cnt]=(edge){t,head[f]};head[f]=cnt;
e[++cnt]=(edge){f,head[t]};head[t]=cnt;
};

void GetRt(int x,int fa)
{
size[x]=1;mx[x]=0;
for(int i=head[x];i;i=e[i].next)
if(!b[e[i].to]&&e[i].to!=fa)
{
GetRt(e[i].to,x);
size[x]+=size[e[i].to];
mx[x]=max(mx[x],size[e[i].to]);
}
int Sz=max(tot-size[x],mx[x]);
if(Sz<mn) mn=Sz,rt=x;
}

void Dfs(int x,int fa,int Dep)
{
++tot;
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=fa&&!b[e[i].to])
{
bel[Dep][e[i].to]=bel[Dep][x];
dep[Dep][e[i].to]=dep[Dep][x]+1;
Dfs(e[i].to,x,Dep);
}
}

void Solve(int x,int Dp)
{
b[x]=1;bel[Dp][x]=++cnt;Mxdp[x]=Dp;dep[Dp][x]=1;
for(int i=head[x];i;i=e[i].next)
if(!b[e[i].to])
{
tot=0;dep[Dp][e[i].to]=2;
bel[Dp][e[i].to]=++cnt;
Dfs(e[i].to,x,Dp);
size[e[i].to]=tot;
}
for(int i=head[x];i;i=e[i].next)
if(!b[e[i].to])
{
tot=size[e[i].to];mn=INF;
GetRt(e[i].to,x);
Fa[Dp+1][rt]=x;
Solve(rt,Dp+1);
}
}

int Query(int x,int v,int lt,int rt)
{
if(!x) return 0;
if(lt==rt) return T[x].x;
int mid=lt+rt>>1,res;
if(v<=mid) res=Query(T[x].l,v,lt,mid);
else       res=Query(T[x].r,v,mid+1,rt);
return res+T[x].x;
}
inline int node(int x){return x?x:++cnt;}
void Modify(int x,int l,int r,int lt,int rt,int v)
{
if(l==lt&&r==rt) {T[x].x+=v;return;}
int mid=lt+rt>>1;
if(r<=mid) Modify(T[x].l=node(T[x].l),l,r,lt,mid,v);
else if(l>mid) Modify(T[x].r=node(T[x].r),l,r,mid+1,rt,v);
else Modify(T[x].l=node(T[x].l),l,mid,lt,mid,v),
Modify(T[x].r=node(T[x].r),mid+1,r,mid+1,rt,v);
}
char op[5];
int main()
{
n=read();m=read();
for(int i=1;i<n;++i) ins(read(),read());
cnt=0;mn=INF;tot=n;GetRt(1,0);Solve(rt,1);
for(int ii=1;ii<=m;++ii)
{
scanf("%s",op+1);
if(op[1]=='Q')
{
int x=read(),sum=0;
for(int j=Mxdp[x],k=x;j;k=Fa[j--][k])
{
sum+=Query(bel[j][k],dep[j][x],1,MN);
if(j!=Mxdp[x])
sum-=Query(bel[j][x],dep[j][x],1,MN);
}
printf("%d\n",sum);
}
else
{
int x=read(),d=read(),w=read();
for(int j=Mxdp[x],k=x;j;k=Fa[j--][k])
if(d-dep[j][x]+2>=1)
{
Modify(bel[j][k],1,d-dep[j][x]+2,1,MN,w);
if(Mxdp[x]!=j)
Modify(bel[j][x],1,d-dep[j][x]+2,1,MN,w);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: