BZOJ5210 最大连通子块和 【树链剖分】【堆】【动态DP】
题目分析:
解决了上次提到的《切树游戏》后,这道题就是一道模板题。
注意我们需要用堆维护子重链的最大值。这样不会使得复杂度变坏,因为每个重链我们只考虑一个点。
时间复杂度$O(nlog^2n)$
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 6 const int maxn = 202000; 7 8 int n,m; 9 int v[maxn]; 10 vector<int> g[maxn]; 11 int fa[maxn],dep[maxn],sz[maxn],son[maxn],top[maxn],tail[maxn]; 12 int where[maxn],number[maxn],num; 13 ll TOT[maxn]; 14 15 struct Priority_queue{ 16 priority_queue <ll,vector<ll>,less<ll> > pq,del; 17 void Insert(ll now){pq.push(now);} 18 void Erase(ll now){del.push(now);} 19 ll Top(){ 20 while(!del.empty()&&pq.top() == del.top()) pq.pop(),del.pop(); 21 return pq.top(); 22 } 23 int Size(){return pq.size()-del.size();} 24 }PQ[maxn]; 25 26 struct node{ll L,R,D,C;}T[maxn<<2]; 27 28 void push_up(int now){ 29 T[now].L = max(T[now<<1].L,T[now<<1].C+T[now<<1|1].L); 30 T[now].R = max(T[now<<1|1].R,T[now<<1|1].C+T[now<<1].R); 31 T[now].D = max(max(T[now<<1].D,T[now<<1|1].D),T[now<<1].R+T[now<<1|1].L); 32 T[now].C = T[now<<1].C+T[now<<1|1].C; 33 } 34 35 node merge(node alpha,node beta){ 36 node gamma; gamma.L = max(alpha.L,alpha.C+beta.L); 37 gamma.R = max(beta.R,beta.C+alpha.R); 38 gamma.D = max(max(alpha.D,beta.D),alpha.R+beta.L); 39 gamma.C = alpha.C+beta.C; 40 return gamma; 41 } 42 43 char readchar(){ 44 char ch = getchar(); while(ch != 'M' && ch != 'Q') ch = getchar(); 45 return ch; 46 } 47 48 void read(){ 49 scanf("%d%d",&n,&m); 50 for(int i=1;i<=n;i++) scanf("%d",&v[i]); 51 for(int i=1;i<n;i++){ 52 int x,y; scanf("%d%d",&x,&y); 53 g[x].push_back(y); g[y].push_back(x); 54 } 55 } 56 57 void dfs1(int now,int f,int dp){ 58 fa[now] = f; dep[now] = dp; 59 for(int i=0;i<g[now].size();i++){ 60 if(g[now][i] == f) continue; 61 dfs1(g[now][i],now,dp+1); 62 sz[now] += sz[g[now][i]]; 63 if(son[now]==0||sz[son[now]]<sz[g[now][i]])son[now]=g[now][i]; 64 } 65 sz[now]++; 66 if(son[now]) tail[now] = tail[son[now]]; 67 else tail[now] = now; 68 } 69 70 void dfs2(int now,int tp){ 71 top[now] = tp;number[now] = ++num; where[num] = now; 72 if(son[now]) dfs2(son[now],tp); 73 for(int i=0;i<g[now].size();i++){ 74 if(g[now][i] == fa[now] || g[now][i] == son[now]) continue; 75 dfs2(g[now][i],g[now][i]); 76 } 77 } 78 79 void Modify(int now,int tl,int tr,int place){ 80 if(tl == tr){ 81 tl = where[tl]; 82 T[now].C = TOT[tl] + v[tl]; 83 T[now].L = max(0ll,TOT[tl]+v[tl]); T[now].R = T[now].L; 84 if(PQ[tl].Size()) T[now].D = max(PQ[tl].Top(),T[now].L); 85 else T[now].D = T[now].L; 86 }else{ 87 int mid = (tl+tr)/2; 88 if(place <= mid) Modify(now<<1,tl,mid,place); 89 else Modify(now<<1|1,mid+1,tr,place); 90 push_up(now); 91 } 92 } 93 94 node Query(int now,int tl,int tr,int l,int r){ 95 if(tl >= l && tr <= r) return T[now]; 96 int mid = (tl+tr)/2; 97 if(r <= mid) return Query(now<<1,tl,mid,l,r); 98 if(l > mid) return Query(now<<1|1,mid+1,tr,l,r); 99 return merge(Query(now<<1,tl,mid,l,r),Query(now<<1|1,mid+1,tr,l,r)); 100 } 101 102 void dfs3(int now){ 103 if(son[now]) dfs3(son[now]); 104 for(int i=0;i<g[now].size();i++){ 105 int mp = g[now][i]; 106 if(mp == fa[now] || mp == son[now]) continue; 107 dfs3(mp); 108 PQ[now].Insert(Query(1,1,n,number[mp],number[tail[mp]]).D); 109 } 110 Modify(1,1,n,number[now]); 111 if(top[now] == now){ 112 long long data = Query(1,1,n,number[now],number[tail[now]]).L; 113 if(data > 0 && fa[now]) TOT[fa[now]]+=data; 114 } 115 } 116 117 void work(){ 118 dfs1(1,0,1); 119 dfs2(1,1); 120 dfs3(1); 121 for(int i=1;i<=m;i++){ 122 char ch = readchar(); 123 if(ch == 'M'){ 124 int x,y; scanf("%d%d",&x,&y); 125 stack<int> sta; int now = top[x]; 126 while(fa[now]) sta.push(now),now = top[fa[now]]; 127 while(!sta.empty()){ 128 int mp = sta.top();sta.pop(); 129 node res = Query(1,1,n,number[mp],number[tail[mp]]); 130 PQ[fa[mp]].Erase(res.D); 131 if(res.L > 0) TOT[fa[mp]]-=res.L; 132 Modify(1,1,n,number[fa[mp]]); 133 } 134 now = x; v[x] = y; 135 while(now){ 136 Modify(1,1,n,number[now]); 137 now = top[now]; 138 node res = Query(1,1,n,number[now],number[tail[now]]); 139 if(res.L > 0 && fa[now]) TOT[fa[now]]+=res.L; 140 PQ[fa[now]].Insert(res.D); 141 now= fa[now]; 142 } 143 }else{ 144 int x; scanf("%d",&x); 145 long long ans = Query(1,1,n,number[x],number[tail[x]]).D; 146 printf("%lld\n",ans); 147 } 148 } 149 } 150 151 int main(){ 152 read(); 153 work(); 154 return 0; 155 }