bzoj4712 -- 树链剖分

题解:http://www.cnblogs.com/clrs97/p/6006305.html

 

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 using namespace std;
  7 #define N 200010
  8 #define ll long long
  9 #define INF 1LL<<60
 10 vector<int>g[N];
 11 ll p[N<<2],c[N<<2],h[N],dp[N],w[N],y,d;
 12 int i,j,k,n,m,Top[N],Num,s[N],W[N],W2[N],f[N],x,Son[N];
 13 char S[3];
 14 inline ll Min(ll x,ll y){return x<y?x:y;}
 15 inline void Dfs(int x,int F){
 16     f[x]=F;s[x]=1;
 17     for(int i=0;i<g[x].size();i++)
 18     if(g[x][i]!=F){
 19         Dfs(g[x][i],x);
 20         if(s[g[x][i]]>s[Son[x]])Son[x]=g[x][i];
 21         s[x]+=s[g[x][i]];
 22         h[x]+=dp[g[x][i]];
 23     }
 24     if(s[x]==1)h[x]=INF;
 25     dp[x]=Min(w[x],h[x]);
 26 }
 27 inline void Dfs2(int x,int Tmp){
 28     Top[x]=Tmp;W[x]=++Num;W2[Num]=x;
 29     if(Son[x])Dfs2(Son[x],Tmp);
 30     for(int i=0;i<g[x].size();i++)
 31     if(g[x][i]!=f[x]&&g[x][i]!=Son[x])Dfs2(g[x][i],g[x][i]);
 32 }
 33 inline void Push(int Node){
 34     c[Node<<1]-=p[Node];c[Node<<1|1]-=p[Node];
 35     p[Node<<1]+=p[Node];p[Node<<1|1]+=p[Node];
 36     p[Node]=0;
 37 }
 38 inline int Find(int Node,int l,int r,int L,int R,ll x){
 39     if(l>=L&&r<=R){
 40         if(c[Node]>=x)return l;
 41         if(l==r)return 0;
 42     }
 43     if(p[Node])Push(Node);
 44     int Mid=l+r>>1;
 45     if(Mid>=R)return Find(Node<<1,l,Mid,L,R,x);
 46     if(Mid<L)return Find(Node<<1|1,Mid+1,r,L,R,x);
 47     int y=Find(Node<<1|1,Mid+1,r,L,R,x);
 48     if(y==0||y>Mid+1)return y;
 49     y=Find(Node<<1,l,Mid,L,R,x);
 50     if(y)return y;
 51     return Mid+1;
 52 }
 53 inline int Get_top(int x,ll d){
 54     int t=x;
 55     while(x){
 56         int y=Find(1,1,n,W[Top[x]],W[x],d);
 57         if(y==0)break;
 58         if(y>W[Top[x]])return W2[y];
 59         t=Top[x];
 60         x=f[t];
 61     }
 62     return t;
 63 }
 64 inline void Build(int Node,int l,int r){
 65     if(l==r){
 66         c[Node]=w[W2[l]]-h[W2[l]];
 67         p[Node]=h[W2[l]];
 68         return;
 69     }
 70     int Mid=l+r>>1;
 71     Build(Node<<1,l,Mid);
 72     Build(Node<<1|1,Mid+1,r);
 73     c[Node]=Min(c[Node<<1],c[Node<<1|1]);
 74 }
 75 inline ll Query(int Node,int l,int r,int x){
 76     if(l==r)return p[Node];
 77     if(p[Node])Push(Node);
 78     int Mid=l+r>>1;
 79     if(x<=Mid)return Query(Node<<1,l,Mid,x);
 80     return Query(Node<<1|1,Mid+1,r,x);
 81 }
 82 inline ll Query_dp(int x){return Min(w[x],Query(1,1,n,W[x]));}
 83 inline void Update_w(int Node,int l,int r,int x,ll y){
 84     if(l==r){c[Node]+=y;return;}
 85     int Mid=l+r>>1;
 86     if(p[Node])Push(Node);
 87     if(Mid>=x)Update_w(Node<<1,l,Mid,x,y);else Update_w(Node<<1|1,Mid+1,r,x,y);
 88     c[Node]=Min(c[Node<<1],c[Node<<1|1]);    
 89 }
 90 inline void Update_h(int Node,int l,int r,int L,int R,ll x){
 91     if(l>R||r<L)return;
 92     if(l>=L&&r<=R){
 93         c[Node]-=x;
 94         p[Node]+=x;
 95         return;
 96     }
 97     if(p[Node])Push(Node);
 98     int Mid=l+r>>1;
 99     Update_h(Node<<1,l,Mid,L,R,x);
100     Update_h(Node<<1|1,Mid+1,r,L,R,x);
101     c[Node]=Min(c[Node<<1],c[Node<<1|1]);
102 }
103 inline void Modify(int x,int y,ll z){
104     while(Top[x]!=Top[y])Update_h(1,1,n,W[Top[x]],W[x],z),x=f[Top[x]];
105     Update_h(1,1,n,W[y],W[x],z);
106 }
107 inline void Update_tree(int x,ll y){
108     ll Tmp=Query_dp(x);
109     w[x]+=y;Update_w(1,1,n,W[x],y);
110     d=Query_dp(x)-Tmp;
111     if(d==0)return;
112     while(f[x]){
113         int z=Get_top(x,d);
114         if(x!=z)Modify(f[x],z,d);
115         x=f[z];
116         if(x==0)return;
117         ll Tmp=Query_dp(x);
118         Update_h(1,1,n,W[x],W[x],d);
119         d=Query_dp(x)-Tmp;
120         if(d==0)return;
121     }
122 }
123 int main(){
124     scanf("%d",&n);
125     for(i=1;i<=n;i++)scanf("%lld",&w[i]);
126     for(i=1;i<n;i++)scanf("%d%d",&x,&y),g[x].push_back(y),g[y].push_back(x);
127     Dfs(1,0);Dfs2(1,1);
128     Build(1,1,n);
129     scanf("%d",&m);
130     while(m--){
131         scanf("%s",S);
132         if(S[0]=='Q')scanf("%d",&x),printf("%lld\n",Query_dp(x));else scanf("%d%lld",&x,&y),Update_tree(x,y);
133     }
134     return 0;
135 }
bzoj4712

 

posted @ 2017-04-24 18:22  gjghfd  阅读(248)  评论(0编辑  收藏  举报