NC23051. 华华和月月种树
描述
输入描述
第一行一个正整数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
C++14(g++5.4) 解法, 执行用时: 118ms, 内存消耗: 23968K, 提交时间: 2020-08-20 12:05:47
#include<bits/stdc++.h> using namespace std; vector<int>R[400005]; int n=0,tot=0,S[400005]={0},in[400005],out[400005],op[400005],x[400005],y[400005]; int lowbit(int x) { return x&(-x); } void update(int i,int x) { while(i<=n+1)S[i]+=x,i+=lowbit(i); } int getsum(int i) { int s=0; while(i)s+=S[i],i-=lowbit(i); return s; } void DFS(int x) { in[x]=++tot; for(int i=0;i<R[x].size();i++)DFS(R[x][i]); out[x]=tot; } int main() { int i,j,m; scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%d%d",&op[i],&x[i]); if(op[i]==2)scanf("%d",&y[i]); if(op[i]==1)R[x[i]].push_back(++n),y[i]=n; } DFS(0); for(i=1;i<=m;i++) { if(op[i]==1)j=getsum(in[y[i]]),update(in[y[i]],-j),update(in[y[i]]+1,j); else if(op[i]==2)update(in[x[i]],y[i]),update(out[x[i]]+1,-y[i]); else printf("%d\n",getsum(in[x[i]])); } }
C++11(clang++ 3.9) 解法, 执行用时: 114ms, 内存消耗: 22424K, 提交时间: 2020-08-20 18:28:46
#include<bits/stdc++.h> using namespace std; vector<int>R[400005]; int n=0,tot=0,S[400005]={0},in[400005],out[400005],op[400005],x[400005],y[400005]; int lowbit(int x){ return x&(-x); } void update(int i,int x){ while(i<=n+1)S[i]+=x,i+=lowbit(i); } int getsum(int i){ int s=0; while(i)s+=S[i],i-=lowbit(i); return s; } void DFS(int x){ in[x]=++tot; for(int i=0;i<R[x].size();i++)DFS(R[x][i]); out[x]=tot; } int main(){ int i,j,m; scanf("%d",&m); for(i=1;i<=m;i++){ scanf("%d%d",&op[i],&x[i]); if(op[i]==2)scanf("%d",&y[i]); if(op[i]==1)R[x[i]].push_back(++n),y[i]=n; } DFS(0); for(i=1;i<=m;i++){ if(op[i]==1)j=getsum(in[y[i]]),update(in[y[i]],-j),update(in[y[i]]+1,j); else if(op[i]==2)update(in[x[i]],y[i]),update(out[x[i]]+1,-y[i]); else printf("%d\n",getsum(in[x[i]])); } }