口胡的弱智型题解:
$f_x$表示$x$的子树中,与$x$联通(或为空集)的最大联通子块和。
$ans_x$表示$x$的子树中,最大联通子块和。
$y is son of x$
$f_x=max(0,sum f_y+v_x)$
$ans_x=max(f_x,ans_y)$
不带修改的话一次树dp即可。
带修改的,考虑用树剖维护,
设$g_x=v_x+sum_{y|y是x的轻儿子}f_y$,$son_x$表示$x$的重儿子
$f_x=max(0,g_x+f_{son_x})$
试着看一条重链,链底的$f_x=g_x=max(0,v_x)$,往上$f_x=max(0,g_x+f_{son_x})$。这就是一个以x开头的最大连续子段和,可以用线段树维护!
也就是说,在线段树上存下每个x的g就可以查到每个x对应的f了。而修改的时候,重链上线段树上修改g,再跳到上一条重链继续修改即可。(第一次修改g是因为v的改变,往上跳修改是因为$f_{轻儿子}$的改变)
再考虑ans的维护。如果用$s_x$表示轻儿子的$ans$的最大值
$ans_x=max(s_x,s_{son_x},f_x)$
$s_x$和$g_x$的差别在于取最大值在修改时不好处理,所以$s_x$不能是一个值(轻儿子的$ans$的最大值)而是一个set(存所有轻儿子的$ans$值),这样s和g的修改就一样操作了。
然后这个$s_x$可以直接放在线段树上,x的节点上,这样很容易取最大值。
而重儿子的ans,是一段最大连续子段最短和,那么对于x来说,这条重链上的所有f,也就是任意位置开始的一段最大连续子段和。这个就也可以用线段树维护,并可以和$s_x$用同一个值维护,就可以在线段树上直接查到x的ans了。
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define Formylove return 0
13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
15 const int N=400007;
16 typedef long long LL;
17 typedef double db;
18 using namespace std;
19 int n,m;
20 LL v[N];
21 char op[5];
22
23 template<typename T>void read(T &x) {
24 char ch=getchar(); x=0; T f=1;
25 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
26 if(ch=='-') f=-1,ch=getchar();
27 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
28 }
29
30 struct sg {
31 LL sum,sl,sr,sm;
32 friend sg operator +(const sg&ls,const sg&rs) {
33 sg a;
34 a.sum=ls.sum+rs.sum;
35 a.sl=max(ls.sl,ls.sum+rs.sl);
36 a.sr=max(rs.sr,rs.sum+ls.sr);
37 a.sm=max(max(ls.sm,rs.sm),ls.sr+rs.sl);
38 return a;
39 }
40 }tr[N<<2];
41 multiset<LL>s[N];
42
43 #define lc x<<1
44 #define rc ((x<<1)|1)
45 #define mid ((l+r)>>1)
46 sg qry(int x,int l,int r,int ql,int qr) {
47 if(l>=ql&&r<=qr) return tr[x];
48 if(qr<=mid) return qry(lc,l,mid,ql,qr);
49 if(ql>mid) return qry(rc,mid+1,r,ql,qr);
50 return qry(lc,l,mid,ql,qr)+qry(rc,mid+1,r,ql,qr);
51 }
52
53 void update(int x,int l,int r,int pos,LL g,LL mg) {
54 if(l==r) {
55 tr[x].sum=g;
56 tr[x].sl=tr[x].sr=max(0LL,g);
57 tr[x].sm=max(mg,g);
58 return ;
59 }
60 if(pos<=mid) update(lc,l,mid,pos,g,mg);
61 else update(rc,mid+1,r,pos,g,mg);
62 tr[x]=tr[lc]+tr[rc];
63 }
64
65 int ecnt,fir[N],nxt[N<<1],to[N<<1];
66 void add(int u,int v) {
67 nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
68 nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
69 }
70
71 int R[N],fa[N],sz[N];
72 void dfs(int x,int Fa) {
73 sz[x]=1;
74 fa[x]=Fa;
75 R[x]=R[Fa]+1;
76 for(int i=fir[x];i;i=nxt[i]) if(to[i]!=Fa) {
77 dfs(to[i],x);
78 sz[x]+=sz[to[i]];
79 }
80 }
81
82 int top[N],ed[N],dfk,tid[N],tot;
83 LL ftf[N],stf[N];
84 void DFS(int x,int Top) {
85 tid[x]=++tot;
86 top[x]=Top;
87 ed[Top]=x;
88 int mson=0;
89 for(int i=fir[x];i;i=nxt[i])
90 if(to[i]!=fa[x]&&(!mson||sz[to[i]]>sz[mson]))
91 mson=to[i];
92 if(!mson) {
93 update(1,1,n,tid[x],v[x],0);
94 return;
95 }
96 DFS(mson,Top);
97 LL gx=v[x],mg=0;
98 for(int i=fir[x];i;i=nxt[i])
99 if(to[i]!=fa[x]&&to[i]!=mson) {
100 DFS(to[i],to[i]);
101 sg tp=qry(1,1,n,tid[to[i]],tid[ed[top[to[i]]]]);
102 gx+=tp.sl;
103 mg=max(mg,tp.sm);
104 s[x].insert(tp.sm);
105 ftf[to[i]]=tp.sl;
106 stf[to[i]]=tp.sm;
107 }
108 update(1,1,n,tid[x],gx,mg);
109 }
110
111 void change(int x,LL y) {
112 sg tp=qry(1,1,n,tid[x],tid[x]),tpz;
113 LL gx=tp.sum-v[x]+y; v[x]=y;
114 LL mg=0; if(!s[x].empty()) mg=*s[x].rbegin();
115 update(1,1,n,tid[x],gx,mg);
116 for(;;) {
117 int z=fa[top[x]];
118 if(!z) break;
119 tp=qry(1,1,n,tid[top[x]],tid[ed[top[x]]]);
120 tpz=qry(1,1,n,tid[z],tid[z]);
121 LL gx=tpz.sum-ftf[top[x]]+tp.sl;
122 s[z].erase(s[z].find(stf[top[x]]));
123 s[z].insert(tp.sm);
124 ftf[top[x]]=tp.sl;
125 stf[top[x]]=tp.sm;
126 LL mg=*s[z].rbegin();
127 update(1,1,n,tid[z],gx,mg);
128 x=z;
129 }
130 }
131
132 int main() {
133 #ifdef ANS
134 freopen(".in","r",stdin);
135 freopen(".out","w",stdout);
136 #endif
137 read(n); read(m);
138 For(i,1,n) read(v[i]);
139 For(i,2,n) {
140 int u,v;
141 read(u); read(v);
142 add(u,v);
143 }
144 dfs(1,0);
145 DFS(1,1);
146 For(ti,1,m) {
147 scanf("%s",op);
148 int x; LL y;
149 if(op[0]=='M') {
150 read(x); read(y);
151 change(x,y);
152 }
153 else {
154 read(x);
155 sg tp=qry(1,1,n,tid[x],tid[ed[top[x]]]);
156 LL ans=tp.sm;
157 printf("%lld
",ans);
158 }
159 }
160 Formylove;
161 }
bzoj4712: 洪水
本来想写题解,但是代码里面注释得已经非常详细了,就放一个别人的题解吧
这种修改操作只有权值加的好像很套路呀。
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define Formylove return 0
13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
15 const int N=400007;
16 typedef long long LL;
17 typedef double db;
18 using namespace std;
19 int n,m;
20 char op[5];
21
22 template<typename T>void read(T &x) {
23 char ch=getchar(); x=0; T f=1;
24 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
25 if(ch=='-') f=-1,ch=getchar();
26 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
27 }
28
29 LL v[N],sg[N<<2],lz[N<<2];
30 #define lc x<<1
31 #define rc ((x<<1)|1)
32 #define mid ((l+r)>>1)
33 void down(int x,int l_len,int r_len) {
34 if(!lz[x]) return;
35 sg[lc]+=lz[x]; lz[lc]+=lz[x];
36 sg[rc]+=lz[x]; lz[rc]+=lz[x];
37 lz[x]=0;
38 }
39
40 LL qry(int x,int l,int r,int ql,int qr) {
41 if(l>=ql&&r<=qr) return sg[x];
42 down(x,mid-l+1,r-mid);
43 if(qr<=mid) return qry(lc,l,mid,ql,qr);
44 if(ql>mid) return qry(rc,mid+1,r,ql,qr);
45 return min(qry(lc,l,mid,ql,qr),qry(rc,mid+1,r,ql,qr));
46 }
47
48 int lef[N];
49 void update(int x,int l,int r,int ql,int qr,LL v) {
50 if(l>=ql&&r<=qr) {
51 if(l==r&&lef[l]) return;
52 sg[x]+=v; if(l!=r) lz[x]+=v; return;
53 }
54 down(x,mid-l+1,r-mid);
55 if(ql<=mid) update(lc,l,mid,ql,qr,v);
56 if(qr>mid) update(rc,mid+1,r,ql,qr,v);
57 sg[x]=min(sg[lc],sg[rc]);
58 }
59
60 int ecnt,fir[N],nxt[N<<1],to[N<<1];
61 void add(int u,int v) {
62 nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
63 nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
64 }
65
66 int fa[N],sz[N];
67 void dfs(int x,int Fa) {
68 sz[x]=1;
69 fa[x]=Fa;
70 for(int i=fir[x];i;i=nxt[i]) if(to[i]!=Fa) {
71 dfs(to[i],x);
72 sz[x]+=sz[to[i]];
73 }
74 }
75
76 int top[N],tid[N],ftid[N],tot;
77 void DFS(int x,int Top) {
78 tid[x]=++tot;
79 ftid[tot]=x;
80 top[x]=Top;
81 int mson=0;
82 for(int i=fir[x];i;i=nxt[i])
83 if(to[i]!=fa[x]&&(!mson||sz[to[i]]>sz[mson]))
84 mson=to[i];
85 if(!mson) {
86 lef[tid[x]]=1;
87 update(1,1,n,tid[x],tid[x],0); //设叶子 v[x]==g[x]
88 return;
89 }
90 LL gx=0;
91 DFS(mson,Top);
92 LL tp=qry(1,1,n,tid[mson],tid[mson]);
93 gx+=min(v[mson],v[mson]-tp);
94 for(int i=fir[x];i;i=nxt[i])
95 if(to[i]!=fa[x]&&to[i]!=mson) {
96 DFS(to[i],to[i]);
97 LL tp=qry(1,1,n,tid[to[i]],tid[to[i]]);
98 gx+=min(v[to[i]],v[to[i]]-tp);
99 }
100 update(1,1,n,tid[x],tid[x],v[x]-gx);
101 }
102
103 void change(int x,LL y) {
104 //v[x]增加了y
105 LL tp=qry(1,1,n,tid[x],tid[x]);
106 LL gx=lef[tid[x]]?v[x]+y:v[x]-tp;//如果是叶子,g始终等于v!!!!
107 update(1,1,n,tid[x],tid[x],y); //v-g增加y
108 if(gx<=v[x]) { //原来选g,现在仍选g
109 v[x]+=y; return;
110 }
111 LL plus;
112 if(v[x]+y<=gx) plus=y; //原来选v,现在选仍v,f增加y
113 else plus=gx-v[x]; //原来选v,现在选g,f增加g-v
114 v[x]+=y;
115 for(;;) {
116 //f[x]增加了plus,即g[z]增加了plus
117 int z=fa[x];
118 if(!z) break;
119 tp=qry(1,1,n,tid[z],tid[z]);
120 LL gz=v[z]-tp;
121 update(1,1,n,tid[z],tid[z],-plus);
122 if(gz>=v[z]) return; //原来选v->g↑,仍选v
123 if(v[z]<=gz+plus) plus=v[z]-gz,x=z; //原来选g->现在选v(由g->v最多n+m次,故可以暴力)
124 else { //原来选g->现在g↑仍选g
125 int t=top[z];
126 int l=tid[t],r=tid[z],rs=r;
127 while(l<=r) {
128 tp=qry(1,1,n,mid,tid[z]);
129 if(tp>=plus) rs=mid,r=mid-1;
130 else l=mid+1;
131 }
132 if(tid[z]>rs) update(1,1,n,rs,tid[z]-1,-plus);
133 x=ftid[rs];
134 }
135 }
136 }
137
138 int main() {
139 #ifdef ANS
140 freopen(".in","r",stdin);
141 freopen(".out","w",stdout);
142 #endif
143 read(n);
144 For(i,1,n) read(v[i]);
145 For(i,2,n) {
146 int u,v;
147 read(u); read(v);
148 add(u,v);
149 }
150 dfs(1,0);
151 DFS(1,1);
152 read(m);
153 For(ti,1,m) {
154 scanf("%s",op);
155 int x; LL y;
156 if(op[0]=='C') {
157 read(x); read(y);
158 change(x,y);
159 }
160 else {
161 read(x);
162 LL ans=qry(1,1,n,tid[x],tid[x]);
163 ans=min(v[x],v[x]-ans);
164 printf("%lld
",ans);
165 }
166 }
167 Formylove;
168 }
169 /*
170 4
171 4 3 2 1
172 1 2
173 1 3
174 4 2
175 4
176 C 4 10
177 Q 1
178 */