1. 程式人生 > >51nod 1199 Money out of Thin Air(線段樹+樹剖分)

51nod 1199 Money out of Thin Air(線段樹+樹剖分)

pri htm ace dfs序 scan turn 連續 algo con

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(線段樹+樹剖分)