隐藏
「bzoj1984」月下“毛景树” - 树链剖分 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「bzoj1984」月下“毛景树” - 树链剖分

题目大意

Change k w:将第k条树枝上毛毛果的个数改变为w个。
Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。
Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。
由于毛毛虫很贪,于是他会有如下询问:
Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

题目分析

这是一道树链剖分的模板代码题。
维护两个标记分别表示修改与增加的值。

  • $add$表示增加懒标记
  • $lazy$表示修改懒标记

每次修改的时候清空$add$标记。
每次增加的时候如果$lazy$有值直接增加$lazy$即可。

不难发现标记不会共存。


细节

这题细节贼多,除了树链剖分维护边权本身的细节外还有如下的细节。
不能用cin,在bzoj会炸。
边根据深度大小反向。

然而这道题我的提交记录是这样的。


RE是因为cin,而TLE是因为:


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
#define O4 __attribute__((__optimize__("-O4")))
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
const int maxn=100005;
struct Tree {
int left,right,max,add,lazy;
Tree(int l=0,int r=0,int m=0,int a=0,int la=-1):left(l),right(r),max(m),add(a),lazy(la) {}
};
int max(int a,int b) {
if(a>b)return a;
return b;
}
struct Segment_Tree {
Tree tree[maxn*4];
#define ls index<<1
#define rs index<<1|1
O4 void build(int index,int Left,int Right) {
tree[index]=Tree(Left,Right);
if(Left==Right)return;
int mid=(Left+Right)>>1;
build(ls,Left,mid);
build(rs,mid+1,Right);
push_up(index);
}
O4 void push_up(int index) {
tree[index].max=max(tree[ls].max,tree[rs].max);
}
O4 void push_down(int index) {
if(tree[index].left==tree[index].right)return;
if(tree[index].lazy!=-1) {
tree[ls].lazy=tree[rs].lazy=tree[index].lazy;
tree[ls].add=tree[rs].add=0;
tree[ls].max=tree[rs].max=tree[index].lazy;
tree[index].lazy=-1;
}
if(tree[index].add) {
if(tree[ls].lazy!=-1)tree[ls].lazy+=tree[index].add;
else tree[ls].add+=tree[index].add;
if(tree[rs].lazy!=-1)tree[rs].lazy+=tree[index].add;
else tree[rs].add+=tree[index].add;
tree[ls].max+=tree[index].add;
tree[rs].max+=tree[index].add;
tree[index].add=0;
}
}
O4 void add(int index,int Left,int Right,int v) {
if(Left>tree[index].right||Right<tree[index].left)return;
if(Left<=tree[index].left&&Right>=tree[index].right) {
if(tree[index].lazy!=-1)tree[index].lazy+=v;
else tree[index].add+=v;
tree[index].max+=v;
return;
}
push_down(index);
add(ls,Left,Right,v);
add(rs,Left,Right,v);
push_up(index);
}
O4 void modify(int index,int Left,int Right,int v) {
if(Left>tree[index].right||Right<tree[index].left)return;
if(Left<=tree[index].left&&Right>=tree[index].right) {
tree[index].add=0;
tree[index].lazy=v;
tree[index].max=v;
return;
}
push_down(index);
modify(ls,Left,Right,v);
modify(rs,Left,Right,v);
push_up(index);
}
O4 int query(int index,int Left,int Right) {
if(Left>tree[index].right||Right<tree[index].left)return 0;
if(Left<=tree[index].left&&Right>=tree[index].right)return tree[index].max;
push_down(index);
return max(query(ls,Left,Right),query(rs,Left,Right));
}
} st;
struct Edge {
int from,to,dist;
} edge[maxn];
vector<int>edges[maxn];
void AddEdge(int x,int y) {
edges[x].push_back(y);
}
int n,father[maxn],Depth[maxn],Size[maxn],Son[maxn],Top[maxn],M[maxn],cnt=0;
O4 void Dfs1(int now,int fa,int depth) {
father[now]=fa;
Depth[now]=depth;
Size[now]=1;
for(int i=0; i<edges[now].size(); i++) {
int next=edges[now][i];
if(next==fa)continue;
Dfs1(next,now,depth+1);
Size[now]+=Size[next];
if(Size[next]>Size[Son[now]])Son[now]=next;
}
}
O4 void Dfs2(int now,int top) {
Top[now]=top;
M[now]=++cnt;
if(Son[now])Dfs2(Son[now],top);
for(int i=0; i<edges[now].size(); i++) {
int next=edges[now][i];
if(next==father[now]||next==Son[now])continue;
Dfs2(next,next);
}
}
O4 void modify(int index,int v) {
st.modify(1,M[edge[index].from],M[edge[index].from],v);
}
O4 void modify(int from,int to,int v) {
if(from==to)return;
int t1=Top[from],t2=Top[to];
while(t1!=t2) {
if(Depth[t1]<Depth[t2]) {
swap(t1,t2);
swap(from,to);
}
st.modify(1,M[t1],M[from],v);
from=father[t1];
t1=Top[from];
}
if(from==to)return;
if(Depth[from]>Depth[to])swap(from,to);
return st.modify(1,M[Son[from]],M[to],v);
}
O4 void add(int from,int to,int v) {
if(from==to)return;
int t1=Top[from],t2=Top[to];
while(t1!=t2) {
if(Depth[t1]<Depth[t2]) {
swap(t1,t2);
swap(from,to);
}
st.add(1,M[t1],M[from],v);
from=father[t1];
t1=Top[from];
}
if(from==to)return;
if(Depth[from]>Depth[to])swap(from,to);
return st.add(1,M[Son[from]],M[to],v);
}
O4 int query(int from,int to) {
int t1=Top[from],t2=Top[to],Max=0;
while(t1!=t2) {
if(Depth[t1]<Depth[t2]) {
swap(t1,t2);
swap(from,to);
}
Max=max(Max,st.query(1,M[t1],M[from]));
from=father[t1];
t1=Top[from];
}
if(from==to)return Max;
if(Depth[from]>Depth[to])swap(from,to);
return max(Max,st.query(1,M[Son[from]],M[to]));
}
O4 int main() {
n=Get_Int();
for(int i=1; i<n; i++) {
int x=Get_Int(),y=Get_Int(),v=Get_Int();
AddEdge(x,y);
AddEdge(y,x);
edge[i]=(Edge) {
x,y,v
};
}
Dfs1(1,0,1);
Dfs2(1,1);
st.build(1,1,cnt);
for(int i=1; i<n; i++) {
if(Depth[edge[i].from]<Depth[edge[i].to])swap(edge[i].from,edge[i].to);
st.modify(1,M[edge[i].from],M[edge[i].from],edge[i].dist);
}
int cnt=0;
while(true) {
char opt[10];
scanf("%s",opt);
if(opt[1]=='h') {
int x=Get_Int(),y=Get_Int();
modify(x,y);
} else if(opt[1]=='o') {
int x=Get_Int(),y=Get_Int(),v=Get_Int();
modify(x,y,v);
} else if(opt[0]=='A') {
int x=Get_Int(),y=Get_Int(),v=Get_Int();
add(x,y,v);
} else if(opt[0]=='M') {
int x=Get_Int(),y=Get_Int();
printf("%d\n",query(x,y));
} else break;
}
return 0;
}
姥爷们赏瓶冰阔落吧~