您的位置:首页 > 其它

BZOJ 4034: [HAOI2015]树上操作【树链剖分】【DFS序】

2017-10-18 19:32 405 查看

Description

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个

操作,分为三种:

操作 1 :把某个节点 x 的点权增加 a 。

操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。

操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

题解

显然,树链剖分的序也是DFS序,直接维护就可以了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100006
#define LL long long
using namespace std;
inline char nc(){
static char buf[100000],*i=buf,*j=buf;
return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline LL _read(){
char ch=nc();LL sum=0,p=1;
while((ch!='-')&&(!(ch>='0'&&ch<='9')))ch=nc();
if(ch=='-')p=-1,ch=nc();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
return sum*p;
}
struct data{
int l,r;
LL sum,tag;
void add(LL k){
sum+=k*(r-l+1);tag+=k;
}
}tree[maxn*4];
int n,T,tot,tem,top[maxn],fa[maxn],id[maxn],num[maxn],dep[maxn],H_son[maxn],lnk[maxn],son[maxn*2],nxt[maxn*2];
LL a[maxn];
bool vis[maxn];
void add(int x,int y){
nxt[++tot]=lnk[x];son[tot]=y;lnk[x]=tot;
}
void pushdown(int p){
if(tree[p].tag==0)return;
tree[p<<1].add(tree[p].tag);tree[p<<1|1].add(tree[p].tag);
tree[p].tag=0;
}
void build(int p,int l,int r){
tree[p].l=l;tree[p].r=r;
if(l>=r)return;
int mid=(l+r)>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
}
void update(int p,int l,int r,LL k){
if(tree[p].r<l||tree[p].l>r)return;
if(l<=tree[p].l&&r>=tree[p].r){
tree[p].add(k);return;
}
pushdown(p);
update(p<<1,l,r,k);update(p<<1|1,l,r,k);
tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
}
LL query(int p,int l,int r){
if(tree[p].r<l||tree[p].l>r)return 0;
if(l<=tree[p].l&&r>=tree[p].r)return tree[p].sum;
pushdown(p);
return query(p<<1,l,r)+query(p<<1|1,l,r);
}
void dfs1(int x){
vis[x]=0;num[x]=1;
for(int j=lnk[x];j;j=nxt[j]) if(vis[son[j]]){
dep[son[j]]=dep[x]+1;fa[son[j]]=x;dfs1(son[j]);
num[x]+=num[son[j]];if(num[son[j]]>num[H_son[x]])H_son[x]=son[j];
}
}
void dfs2(int x,int y){
vis[x]=0;top[x]=y;id[x]=++tem;update(1,tem,tem,a[x]);
if(vis[H_son[x]]&&H_son[x]>0)dfs2(H_son[x],y);
for(int j=lnk[x];j;j=nxt[j]) if(vis[son[j]]&&son[j]!=H_son[x])dfs2(son[j],son[j]);
}
LL get(int x,int y){
LL sum=0;
for(;top[x]!=top[y];x=fa[top[x]]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
sum+=query(1,id[top[x]],id[x]);
}
if(id[x]>id[y])swap(x,y);
return sum+query(1,id[x],id[y]);
}
int main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
n=_read();T=_read();
build(1,1,n);
for(int i=1;i<=n;i++)a[i]=_read();
for(int i=1,x,y;i<n;i++)x=_read(),y=_read(),add(x,y),add(y,x);
memset(vis,1,sizeof(vis));dfs1(1);
memset(vis,1,sizeof(vis));dfs2(1,1);
while(T--){
int k=_read(),x=_read(),y;
if(k==1)y=_read(),update(1,id[x],id[x],y);else
if(k==2)y=_read(),update(1,id[x],id[x]+num[x]-1,y);else
if(k==3)printf("%lld\n",get(x,1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: