51nod 1199 Money out of Thin Air(线段树+树剖分)

Posted 谦谦君子,陌上其华

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1199 Money out of Thin Air(线段树+树剖分)相关的知识,希望对你有一定的参考价值。

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1199

题意:

 

思路:
因为是一棵树,所以需要把它剖分一下再映射到线段树上,剖分的话只需要dfs一遍树即可,得到的dfs序就是每个结点在线段树中的位置,子树上的节点的编号都是连续的。

接下来的操作就是线段树的查询和更新了,这部分并不难。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<vector>
  6 #include<stack>
  7 #include<queue>
  8 #include<cmath>
  9 #include<map>
 10 #include<set>
 11 using namespace std;
 12 typedef long long ll;
 13 const int INF = 0x3f3f3f3f;
 14 const int maxn=50000+5;
 15 
 16 ll n, m, dfs_clock;
 17 int w[maxn],son[maxn],dfn[maxn],num[maxn];
 18 ll lazy[maxn<<2];
 19 
 20 vector<int> G[maxn];
 21 
 22 struct node
 23 {
 24     int l, r;
 25     ll sum;
 26 }t[maxn<<2];
 27 
 28 void dfs(int u)
 29 {
 30     dfn[u]=++dfs_clock;
 31     son[u]=1;
 32     for(int i=0;i<G[u].size();i++)
 33     {
 34         int v=G[u][i];
 35         dfs(v);
 36         son[u]+=son[v];
 37     }
 38 }
 39 
 40 void PushUp(int o)
 41 {
 42     t[o].sum=t[o<<1].sum+t[o<<1|1].sum;
 43 }
 44 
 45 void PushDown(int o)
 46 {
 47     if(lazy[o])
 48     {
 49         lazy[o<<1]+=lazy[o];
 50         lazy[o<<1|1]+=lazy[o];
 51         int m=t[o].r-t[o].l+1;
 52         t[o<<1].sum+=lazy[o]*(m-(m>>1));
 53         t[o<<1|1].sum+=lazy[o]*(m>>1);
 54         lazy[o]=0;
 55     }
 56 }
 57 
 58 void build(int l ,int r, int o)
 59 {
 60     lazy[o]=0;
 61     t[o].l=l;
 62     t[o].r=r;
 63     t[o].sum=0;
 64     if(l==r)
 65     {
 66         t[o].sum=num[l];
 67         return;
 68     }
 69     int mid=(l+r)>>1;
 70     build(l,mid,o<<1);
 71     build(mid+1,r,o<<1|1);
 72     PushUp(o);
 73 }
 74 
 75 void update(int ql, int qr, int l, int r, ll z, int o)
 76 {
 77     if(ql<=l && qr>=r)
 78     {
 79         t[o].sum+=(r-l+1)*z;
 80         lazy[o]+=z;
 81         return;
 82     }
 83     PushDown(o);
 84     int mid=(l+r)>>1;
 85     if(ql<=mid)  update(ql,qr,l,mid,z,o<<1);
 86     if(qr>mid)  update(ql,qr,mid+1,r,z,o<<1|1);
 87     PushUp(o);
 88 }
 89 
 90 ll query(int ql, int qr, int l, int r, int o)
 91 {
 92     if(ql<=l && qr>=r)  return t[o].sum;
 93     PushDown(o);
 94     int mid=(l+r)>>1;
 95     ll ans=0;
 96     if(ql<=mid)  ans+=query(ql,qr,l,mid,o<<1);
 97     if(qr>mid)   ans+=query(ql,qr,mid+1,r,o<<1|1);
 98     return ans;
 99 }
100 
101 int main()
102 {
103     //freopen("in.txt","r",stdin);
104     scanf("%d%d",&n,&m);
105     for(int i=0;i<n;i++)  G[i].clear();
106     for(int i=1;i<n;i++)
107     {
108         int p; scanf("%d%d",&p,&w[i]);
109         G[p].push_back(i);
110     }
111     w[0]=0;
112     dfs_clock=0;
113     dfs(0);
114     for(int i=0;i<n;i++)  num[dfn[i]]=w[i];
115     build(1,n,1);
116     char op[3]; ll x, y, z;
117     memset(lazy,0,sizeof(lazy));
118     while(m--)
119     {
120         scanf("%s%lld%lld%lld",op,&x,&y,&z);
121         if(op[0]==\'S\')
122         {
123             if(query(dfn[x],dfn[x],1,n,1)<y)  update(dfn[x],dfn[x],1,n,z,1);
124         }
125         else
126         {
127             if(query(dfn[x],dfn[x]+son[x]-1,1,n,1)<son[x]*y)  update(dfn[x],dfn[x]+son[x]-1,1,n,z,1);
128         }
129     }
130     for(int i=0;i<n;i++)  printf("%lld\\n",query(dfn[i],dfn[i],1,n,1));
131     return 0;
132 }

 

以上是关于51nod 1199 Money out of Thin Air(线段树+树剖分)的主要内容,如果未能解决你的问题,请参考以下文章

51nod_1199 树的先跟遍历+区间更新树状数组

Money out of Thin Air

51Nod——T 1631 小鲨鱼在51nod小学

51Nod——T 1686 第K大区间

51Nod 1228 序列求和

QM1_Time value of Money