洛谷P3833 [SHOI2012]魔法树
题目
https://www.luogu.com.cn/problem/P3833
思路
思路?义眼丁真,鉴定为:纯纯的板题。
但是我是傻逼,符号写反WA了两发,得赶紧找点数据结构题练练手。
代码
点击查看代码
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define maxn 100010
#define ll long long
using namespace std;
int fst[maxn],nxt[maxn],to[maxn],cnt=0,fa[maxn];
int son[maxn],sz[maxn],deep[maxn],top[maxn],dfn[maxn],idx=0;
int l[maxn<<2],r[maxn<<2];
ll sum[maxn<<2],tag[maxn<<2];
void addedge(int x,int y){
to[++cnt]=y;
nxt[cnt]=fst[x];
fst[x]=cnt;
}
void dfs1(int x){
sz[x]++;
deep[x]=deep[fa[x]]+1;
for(int i=fst[x];i;i=nxt[i]){
if(to[i]==fa[x]) continue;
dfs1(to[i]);
sz[x]+=sz[to[i]];
if(sz[to[i]]>sz[son[x]]) son[x]=to[i];
}
}
void dfs2(int x){
dfn[x]=++idx;
if(son[fa[x]]==x) top[x]=top[fa[x]];
else top[x]=x;
if(son[x]) dfs2(son[x]);
for(int i=fst[x];i;i=nxt[i]){
if(to[i]==fa[x]||to[i]==son[x]) continue;
dfs2(to[i]);
}
}
void build(int x,int left,int right){
l[x]=left,r[x]=right;
if(left==right) return;
int mid=left+right>>1;
build(x<<1,left,mid);
build(x<<1|1,mid+1,right);
}
void update(int x){
sum[x]=sum[x<<1]+sum[x<<1|1];
}
void pushdown(int x){
if(tag[x]){
tag[x<<1]+=tag[x];
tag[x<<1|1]+=tag[x];
sum[x<<1]+=tag[x]*(r[x<<1]-l[x<<1]+1);
sum[x<<1|1]+=tag[x]*(r[x<<1|1]-l[x<<1|1]+1);//sum[x>>1|1]+=tag[x]*(r[x<<1|1]-l[x<<1|1]+1);woshishabi
tag[x]=0;
}
}
void modify(int x,int left,int right,ll k){
if(l[x]>=left&&r[x]<=right){
sum[x]+=k*(r[x]-l[x]+1);
tag[x]+=k;
return;
}
pushdown(x);
int mid=l[x]+r[x]>>1;
if(left<=mid) modify(x<<1,left,right,k);
if(right>mid) modify(x<<1|1,left,right,k);
update(x);
}
void change(int x,int y,int d){
while(top[x]!=top[y]){
if(deep[top[x]]>deep[top[y]]) swap(x,y);
modify(1,dfn[top[y]],dfn[y],d);
y=fa[top[y]];
}
if(deep[x]>deep[y]) swap(x,y);
modify(1,dfn[x],dfn[y],d);
}
ll query(int x,int left,int right){
ll r1=0,r2=0;
if(l[x]>=left&&r[x]<=right) return sum[x];
int mid=l[x]+r[x]>>1;
pushdown(x);
if(left<=mid) r1=query(x<<1,left,right);
if(right>mid) r2=query(x<<1|1,left,right);
update(x);
return r1+r2;
}
int main(){
int i,j,n,m,x,y,d;
ll ans;
char op[3];
scanf("%d",&n);
for(i=2;i<=n;++i){
scanf("%d%d",&x,&y);
fa[y+1]=x+1;
addedge(x+1,y+1);
}
dfs1(1);dfs2(1);
build(1,1,n);
scanf("%d",&m);
for(i=1;i<=m;++i){
scanf("%s",op);
if(op[0]=='A'){
scanf("%d%d%d",&x,&y,&d);
change(x+1,y+1,d);
}
else{
scanf("%d",&x);
ans=query(1,dfn[x+1],dfn[x+1]+sz[x+1]-1);
printf("%lld\n",ans);
}
}
// system("pause");
return 0;
}