51Nod 1199 Money out of Thin Air(dfs序+线段树维护区间和)
来源:互联网 发布:新版淘宝店图片大小 编辑:程序博客网 时间:2024/05/21 09:30
一棵有N个节点的树,每个节点对应1个编号及1个权值,有2种不同的操作。
操作1:S x y z,表示如果编号为x的节点的权值 < y,则将节点x的权值加上z。(Single)
操作2:A x y z,表示如果编号为x的节点以及其所有子节点的权值平均值 < y,则将节点x及其所有子节点的权值加上z。(All)
给出树节点之间的关系,进行M次操作,问所有操作完成后,各个节点的权值为多少?
节点的编号为0 - N - 1,根节点的编号为0,并且初始情况下,根节点的权值也是0。
Input
第1行:2个数N, M,N为节点的数量,M为操作的数量(1 <= N, M <= 50000)。
第2 - N行:每行描述一个节点N[i]的信息,第2行对应编号为1的节点,第N行对应编号为N - 1的节点。具体内容为:每行2个数P[i], W[i]。P[i]为当前节点的父节点的编号,W[i]为当前节点的权值。(0 <= W[i] <= 10^5, P[i] < i)
第N + 1 - N + M行:每行表示一个操作,S x y z或A x y z,(0 <= y, z <= 10^5)。
Output
输出共N行,每行1个数W[i],表示经过M次后,编号为0 - N - 1的节点的权值。
Input示例
4 3
0 10
0 10
1 2
S 0 1 1
A 0 20 1
S 3 2 1
Output示例
2
11
11
3
思路:先跑一遍dfs序,求出每个节点的管辖区间,然后线段是维护即可
#include <bits/stdc++.h>#define FIN freopen("input.txt","r",stdin);#define FOUT freopen("output.txt","w+",stdout);using namespace std;typedef long long ll;const int INF = 0x3f3f3f3f;const int mod = 998244353;const double eps=1e-8;const double Pi=acos(-1.0);const int N= 50005;struct T{ ll val; ll addmark;} tree[N<<4];struct node{ int to; ll val;};vector<node> G[N];int L[N],R[N];ll W[N];int n,m,ti;void addedge(int u,int v,ll w){ G[u].push_back((node){v,w}); G[v].push_back((node){u,w});}void init(){ ti=0; for(int i=0; i<=n; i++) G[i].clear(); memset(L,0,sizeof(L)); memset(R,0,sizeof(R)); memset(W,0,sizeof(W)); memset(tree,0,sizeof(tree));}void dfs(int u,int w,int per){ L[u]=++ti; W[ti]=w; for(int i=0; i<(int)G[u].size(); i++) { int v=G[u][i].to; int c=G[u][i].val; if(v==per) continue; dfs(v,c,u); } R[u]=ti;}void build(int root,int l,int r){ if(l==r) tree[root].val=W[l]; else { int mid=(l+r)>>1; build(root<<1,l,mid); build(root<<1|1,mid+1,r); tree[root].val=tree[root<<1].val+tree[root<<1|1].val; }}void push_down(int root,int l,int r){ if(tree[root].addmark!=0) { int mid=(l+r)>>1; tree[root<<1].addmark+=tree[root].addmark; tree[root<<1|1].addmark+=tree[root].addmark; tree[root<<1].val+=tree[root].addmark*(mid-l+1); tree[root<<1|1].val+=tree[root].addmark*(r-(mid+1)+1); tree[root].addmark=0; }}ll query(int root,int l,int r,int b,int e){ if(b>r||e<l) return 0; if(b<=l&&r<=e) return tree[root].val; push_down(root,l,r); int mid=(l+r)>>1; ll sum=0; sum+=query(root<<1,l,mid,b,e); sum+=query(root<<1|1,mid+1,r,b,e); return sum;}void simple_updata(int root,int l,int r,int ind,ll add){ if(l==r) { tree[root].val+=add; return ; } int mid=(l+r)>>1; if(ind<=mid) simple_updata(root<<1,l,mid,ind,add); else simple_updata(root<<1|1,mid+1,r,ind,add); tree[root].val=tree[root<<1].val+tree[root<<1|1].val;}void interval_updata(int root,int l,int r,int b,int e,ll add){ if(b>r||e<l) return ; if(b<=l&&r<=e) { tree[root].addmark+=add; tree[root].val+=add*(r-l+1); return ; } push_down(root,l,r); int mid=(l+r)>>1; interval_updata(root<<1,l,mid,b,e,add); interval_updata(root<<1|1,mid+1,r,b,e,add); tree[root].val=tree[root<<1].val+tree[root<<1|1].val;}int main(){ init(); scanf("%d %d",&n,&m); int u; ll w; for(int i=1; i<n; i++) { scanf("%d %I64d",&u,&w); addedge(u,i,w); } dfs(0,0,-1);// for(int i=1;i<=n;i++)// printf("%d\n",W[i]);// for(int i=0;i<n;i++)// printf("i:%d L:%d R:%d\n",i,L[i],R[i]); build(1,1,n); char ch; int x; ll y,z,num; for(int i=0;i<m;i++) { getchar(); scanf("%c %d %I64d %I64d",&ch,&x,&y,&z); if(ch=='S') { num=query(1,1,n,L[x],L[x]); //printf("i:%d simple:%I64d\n",i+1,num); if(num<y) simple_updata(1,1,n,L[x],z); } else if(ch=='A') { num=query(1,1,n,L[x],R[x]); //printf("i:%d interval:%I64d\n",i+1,num); if((num/(R[x]-L[x]+1))<y) interval_updata(1,1,n,L[x],R[x],z); } } for(int i=0;i<n;i++) printf("%I64d\n",query(1,1,n,L[i],L[i]));}
阅读全文
0 0
- 51Nod 1199 Money out of Thin Air(dfs序+线段树维护区间和)
- 51nod 1199 Money out of Thin Air[线段树]
- 【51nod】1199 Money out of Thin Air 线段树
- 51nod 1199 Money out of Thin Air
- 51Nod-1199-Money out of Thin Air
- out of thin air 凭空;无中生有
- 51nod 1376【线段树维护区间最大值】
- 51nod-1376(线段树维护区间最值)
- spojGSS1 线段树维护区间和最大值
- 51NOD 1672 区间交 线段树
- 线段树区间维护upcoj
- 线段树区间维护hdu3308
- 线段树区间维护hdu3397
- 线段树区间维护cf46D
- POJ3468 线段树区间维护
- hdu 5381 The sum of gcd (线段树x树状数组x区间和维护进阶x离线处理)
- HDU 4288 Coder 线段树维护区间%5的和
- hdu 4578 Transformation(线段树维护区间次方和)
- QT SSL QSslSocket: cannot call unresolved function SSLv23_client_method
- 子串和(南阳理工oj-题目44)
- SpringMVC(4.x) 从搭建到放弃(含源码分析)——一
- 直播+产品的商业化探索和思考
- 「端口扫描工具masscan」手把手教你在Ubuntu上安装masscan
- 51Nod 1199 Money out of Thin Air(dfs序+线段树维护区间和)
- PTA-自测-5 Shuffling Machine
- tf.train中的Optimizer相关的函数与功能介绍
- MFC中添加Richedit2.0控件导致程序无法运行的解决方法
- 51nod 最大M子段和
- Oracle里的哈希连接原理
- 单例模式
- #1149 : 回文字符序列
- 暑期学习记录13