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 }