链接:https://ac.nowcoder.com/acm/contest/392/H
牛客网
华华和月月种树
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
华华看书了解到,一起玩养成类的游戏有助于两人培养感情。所以他决定和月月一起种一棵树。因为华华现在也是信息学高手了,所以他们种的树是信息学意义下的。
华华和月月一起维护了一棵动态有根树,每个点有一个权值。刚开存档的时候,树上只有 0 号节点,权值为 0 。接下来有两种操作:
操作 1:输入格式1 i1 i,表示月月氪金使节点 i 长出了一个新的儿子节点,权值为0,编号为当前最大编号 +1(也可以理解为,当前是第几个操作 1,新节点的编号就是多少)。
操作 2:输入格式 2 i a2 i a,表示华华上线做任务使节点 i 的子树中所有节点(即它和它的所有子孙节点)权值加 a 。
但是月月有时会检查华华有没有认真维护这棵树,会作出询问:
询问 3:输入格式3 i3 i,华华需要给出 i 节点此时的权值。
华华当然有认真种树了,不过还是希望能写个程序以备不时之需。
输入描述:
第一行一个正整数M,接下来M行,每行先输入一个正整数O表示操作类型,再输入一个非负整数i表示操作或询问的节点编号,如果O=2,再输入一个正整数a。
输出描述:
对于每个询问3,输出一个非负整数表示询问的答案。
示例1
输入
复制
9
1 0
2 0 1
3 0
3 1
1 0
1 1
2 0 2
3 1
3 3
输出
复制
1
1
3
2
备注:
1≤M≤4×1051≤M≤4×105,保证操作1的数量不超过105105,保证操作2中的参数a满足1≤a≤999
这个题是个妙题,不会写,看题解:
居然可以这样写,于是我按着题解给的思路写,结果是:
太不容易了,写了近两个小时,可算写出来了,犯了很多细节毛病,AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10;
struct node
{
int ty,x,y;
}q[N];
int n;
vector<int>G[N];
int dfn[N],inde,num[N];
ll sum[N],lazy[N];
void pushdown(int id,int l,int r)
{
if(lazy[id])
{
lazy[id<<1]+=lazy[id];
lazy[id<<1|1]+=lazy[id];
sum[id<<1]+=lazy[id];
sum[id<<1|1]+=lazy[id];
lazy[id]=0;
}
}
ll qu(int id,int l,int r,int pos)
{
if(l==r) return sum[id];
pushdown(id,l,r);
int mid=l+r>>1;
if(pos<=mid) return qu(id<<1,l,mid,pos);
else return qu(id<<1|1,mid+1,r,pos);
}
int dfs(int root)
{
dfn[root]=++inde;
if(G[root].size()==0) return 1;
int ans=0;
for(int i=0;i<G[root].size();++i)
{
ans+=dfs(G[root][i]);
}
num[dfn[root]]=ans;
return num[dfn[root]]+1;
}
void up_1(int id,int l,int r,int pos)
{
if(l==r) {
sum[id]=0;
return ;
}
pushdown(id,l,r);
int mid=l+r>>1;
if(pos<=mid) up_1(id<<1,l,mid,pos);
else up_1(id<<1|1,mid+1,r,pos);
}
void up(int id,int l,int r,int ql,int qr,int v)
{
if(l==r)
{
sum[id]+=v;
return ;
}
if(ql<=l&&r<=qr)
{
lazy[id]+=v;
return ;
}
pushdown(id,l,r);
int mid=l+r>>1;
if(ql<=mid) up(id<<1,l,mid,ql,qr,v);
if(qr>mid) up(id<<1|1,mid+1,r,ql,qr,v);
}
int main()
{
cin>>n;
int cnt=0;
for(int i=1;i<=n;i++){
int ty,x,y;
scanf("%d%d",&ty,&x);
q[i].ty=ty; q[i].x=x;
if(ty==1) G[x].push_back(++cnt);
else if(ty==2) scanf("%d",&q[i].y);
}
int aa=dfs(0);
int cntt=0;
for(int i=1;i<=n;++i)
{
if(q[i].ty==1) up_1(1,1,inde,dfn[++cntt]);
else if(q[i].ty==2)
{
int l=dfn[q[i].x],r=dfn[q[i].x]+num[dfn[q[i].x]];
up(1,1,inde,l,r,q[i].y);
}
else
{
ll ans=qu(1,1,inde,dfn[q[i].x]);
printf("%lld\n",ans);
}
}
}