[luogu]月下“毛景树”:树 剖 好 题

原题


 

题意:

给一棵树 , 每一条边都有边权 , 支持四种操作

1. 将第k条边权值修改为k

2. 将节点u到v的边权都覆盖为k

3. 将节点u到v的边权都增加k

4. 询问区间边权最大值


 

显然树剖

边权转点权然后就是树剖裸题了

怎样边权转点权


 

对于一个点u , 她的父亲是 v

将 u->v 的边权放到 u 上做点权

然后树剖最后的时候这样操作一波

1     if(a == b)
2         return;
3     if(dep[a] > dep[b])
4         std::swap(a, b);
5     SgCover(1, id[a] + 1, id[b], k);

这样就保证了这两个点的 LCA 的点权不会被统计(LCA的点权指向的是 LCA->fa[LCA]  , 很显然不能统计)


 

另一个问题 , 线段树的lazytag

我维护了两个懒标记

一个是 cov , 是覆盖的懒标记

一个是 add , 是增加的懒标记

至于具体用法还是看代码吧 ... 挺好理解的


 

代码:

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<iostream>
  6 #include<algorithm>
  7 #define APART puts("----------------------")
  8 #define debug 1
  9 #define FILETEST 1
 10 #define inf 100010
 11 #define ll long long
 12 #define ha 998244353
 13 #define INF 0x7fffffff
 14 #define INF_T 9223372036854775807
 15 #define DEBUG printf("%s %d\n",__FUNCTION__,__LINE__)
 16 
 17 namespace chino{
 18 
 19 inline void setting(){
 20 #if FILETEST
 21     freopen("_test.in", "r", stdin);
 22     freopen("_test.me.out", "w", stdout);
 23 #endif
 24     return;
 25 }
 26 
 27 inline int read(){
 28     char c = getchar(), up = c; int num = 0;
 29     for(; c < '0' || c > '9'; up = c, c = getchar());
 30     for(; c >= '0' && c <= '9'; num = (num << 3) + (num << 1) + (c ^ '0'), c = getchar());
 31     return  up == '-' ? -num : num;
 32 }
 33 
 34 int n;
 35 int cntE, cntT;
 36 char s[inf];
 37 int mem[inf];
 38 int top[inf];
 39 int dep[inf];
 40 int son[inf];
 41 int fa[inf];
 42 int size[inf];
 43 int id[inf];
 44 int val[inf];
 45 int head[inf << 1];
 46 struct Edge{
 47     int to;
 48     int val;
 49     int next;
 50 }e[inf << 1];
 51 struct Tree{
 52     int l;
 53     int r;
 54     int max;
 55     int cov;
 56     int add;
 57 }t[inf << 2];
 58 std::pair <int, int> p[inf];
 59 #define lson(a) (a) << 1
 60 #define rson(a) (a) << 1 | 1
 61 
 62 inline void AddEdge(int from, int to, int val){
 63     ++cntE;
 64     e[cntE].to = to;
 65     e[cntE].val = val;
 66     e[cntE].next = head[from];
 67     head[from] = cntE;
 68     return; 
 69 }
 70 
 71 inline int getVal(int now){
 72     if(mem[now])
 73         return mem[now];
 74     for(int i = head[now]; i; i = e[i].next){
 75         if(fa[now] == e[i].to)
 76             return mem[now] = e[i].val;
 77     }
 78     return mem[now] = -INF;
 79 }
 80 
 81 void Dfs1(int now, int f, int depth){
 82     fa[now] = f;
 83     dep[now] = depth;
 84     size[now] = 1;
 85     int heavy = -INF;
 86     for(int i = head[now]; i; i = e[i].next){
 87         int to = e[i].to;
 88         if(to == f)
 89             continue;
 90         Dfs1(to, now, depth + 1);
 91         int y = size[to];
 92         size[now] += y;
 93         if(y > heavy){
 94             heavy = y;
 95             son[now] = to;
 96         }
 97     }
 98     return;
 99 }
100 
101 void Dfs2(int now, int point){
102     ++cntT;
103     top[now] = point;
104     id[now] = cntT;
105     val[cntT] = (now == 1 ? -INF : getVal(now));
106     if(son[now] == 0)
107         return;
108     Dfs2(son[now], point);
109     for(int i = head[now]; i; i = e[i].next){
110         int to = e[i].to;
111         if(to == fa[now] || to == son[now])
112             continue;
113         Dfs2(to, to);
114     }
115     return;
116 }
117 
118 using std::max;
119 
120 inline void updata(int now){
121     t[now].max = max (t[lson(now)].max , t[rson(now)].max);
122     return;
123 }
124 
125 inline void pushtag(int now){
126     if(t[now].cov != -INF){
127         t[lson(now)].max = t[now].cov;
128         t[rson(now)].max = t[now].cov;
129         t[lson(now)].cov = t[now].cov;
130         t[rson(now)].cov = t[now].cov;
131         t[lson(now)].add = 0;
132         t[rson(now)].add = 0;
133         t[now].cov = -INF;
134     }
135     if(t[now].add != 0){
136         t[lson(now)].max += t[now].add;
137         t[rson(now)].max += t[now].add;
138         t[lson(now)].add += t[now].add;
139         t[rson(now)].add += t[now].add;
140         t[now].add = 0;
141     }
142     return;
143 }
144 
145 void build(int now, int l, int r){
146     t[now].l = l;
147     t[now].r = r;
148     t[now].cov = -INF;
149     if(l == r){
150         t[now].max = val[l];
151         return;
152     }
153     int mid = (l + r) >> 1;
154     build(lson(now), l, mid);
155     build(rson(now), mid + 1, r);
156     updata(now);
157     return;
158 }
159 void SgCover(int now, int l, int r, int k){
160     if(t[now].l >= l && t[now].r <= r){
161         t[now].cov = t[now].max = k;
162         t[now].add = 0;
163         return;
164     }
165     pushtag(now);
166     int mid = (t[now].l + t[now].r) >> 1;
167     if(l <= mid)
168         SgCover(lson(now), l, r, k);
169     if(r > mid)
170         SgCover(rson(now), l, r, k);
171     updata(now);
172     return;
173 }
174 
175 void SgAdd(int now, int l, int r, int k){
176     if(t[now].l >= l && t[now].r <= r){
177         t[now].add += k;
178         t[now].max += k;
179         return;
180     }
181     pushtag(now);
182     int mid = (t[now].l + t[now].r) >> 1;
183     if(l <= mid)
184         SgAdd(lson(now), l, r, k);
185     if(r > mid)
186         SgAdd(rson(now), l, r, k);
187     updata(now);
188     return; 
189 }
190 
191 void SgChange(int now, int x, int k){
192     if(t[now].l > x || t[now].r < x)
193         return;
194     if(t[now].l == t[now].r){
195         t[now].max = k;
196         t[now].cov = -INF;
197         t[now].add = 0;
198         return;
199     }
200     pushtag(now);
201     int mid = (t[now].l + t[now].r) >> 1;
202     if(x <= mid)
203         SgChange(lson(now), x, k);
204     else 
205         SgChange(rson(now), x, k);
206     updata(now);
207     return;
208 }
209 
210 int SgQuery(int now, int l, int r){
211     if(t[now].l >= l && t[now].r <= r)
212         return t[now].max;
213     pushtag(now);
214     int mid = (t[now].l + t[now].r) >> 1;
215     int Max = -INF;
216     if(l <= mid)
217         Max = max (Max, SgQuery(lson(now), l, r));
218     if(r > mid)
219         Max = max (Max, SgQuery(rson(now), l, r));
220     return Max;
221 }
222 
223 inline void cover(int a, int b, int k){
224     while(top[a] != top[b]){
225         if(dep[top[a]] < dep[top[b]])
226             std::swap(a, b);
227         SgCover(1, id[top[a]], id[a], k);
228         a = fa[top[a]];
229     }
230     if(a == b)
231         return;
232     if(dep[a] > dep[b])
233         std::swap(a, b);
234     SgCover(1, id[a] + 1, id[b], k);
235     return;
236 } 
237 
238 inline void add(int a, int b, int k){
239     while(top[a] != top[b]){
240         if(dep[top[a]] < dep[top[b]])
241             std::swap(a, b);
242         SgAdd(1, id[top[a]], id[a], k);
243         a = fa[top[a]];
244     }
245     if(a == b)
246         return;
247     if(dep[a] > dep[b])
248         std::swap(a, b);
249     SgAdd(1, id[a] + 1, id[b], k);
250     return;
251 }
252 
253 inline int query(int a, int b){
254     int ans = -INF;
255     while(top[a] != top[b]){
256         if(dep[top[a]] < dep[top[b]])
257             std::swap(a, b);
258         ans = max (ans, SgQuery(1, id[top[a]], id[a]));
259         a = fa[top[a]];
260     }
261     if(a == b)
262         return ans;
263     if(dep[a] > dep[b])
264         std::swap(a, b);
265     ans = max (ans, SgQuery(1, id[a] + 1, id[b]));
266     return ans;
267 }
268 
269 inline int main(){
270     n = read();
271     for(int i = 1; i < n; i++){
272         p[i].first  = read();
273         p[i].second = read();
274         int w = read();
275         AddEdge(p[i].first, p[i].second, w);
276         AddEdge(p[i].second, p[i].first, w);
277     }
278     Dfs1(1, 0, 1);
279     Dfs2(1, 1);
280     build(1, 1, n);
281     while(true){
282         scanf("%s", s + 1);
283         if(s[1] == 'S')
284             break;
285         int a = read();
286         int b = read();
287         if(s[2] == 'a'){
288             int ans = query(a, b);
289             printf("%d\n", ans == -INF ? 0 : ans);
290         } else if(s[2] == 'o')
291             cover(a, b, read());
292         else if(s[2] == 'h'){
293             if(fa[p[a].first] == p[a].second)
294                 SgChange(1, id[p[a].first], b);
295             else 
296                 SgChange(1, id[p[a].second],b);
297         } else
298             add(a, b, read());
299     }
300     return 0;
301 }
302 
303 }//namespace chino
304 
305 signed main(){return chino::main();}

附:这题好难写啊 .. 可能是因为我太菜了 .. 很久以前就写过 ... 然后挂了0pts ... 实在不想调一个 350 行的程序 ... 后来今天重构了一遍 ... 不过还是依靠对拍 debug 了好几个小时 ... 码力不行啊 ... 


 

三倍经验

两道Qtree题

题目1

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<iostream>
  6 #include<algorithm>
  7 #define APART puts("----------------------")
  8 #define debug 1
  9 #define FILETEST 1
 10 #define inf 100010
 11 #define ll long long
 12 #define ha 998244353
 13 #define INF 0x7fffffff
 14 #define INF_T 9223372036854775807
 15 #define DEBUG printf("%s %d\n",__FUNCTION__,__LINE__)
 16 
 17 namespace chino{
 18 
 19 inline void setting(){
 20 #if FILETEST
 21     freopen("_test.in", "r", stdin);
 22     freopen("_test.me.out", "w", stdout);
 23 #endif
 24     return;
 25 }
 26 
 27 inline int read(){
 28     char c = getchar(), up = c; int num = 0;
 29     for(; c < '0' || c > '9'; up = c, c = getchar());
 30     for(; c >= '0' && c <= '9'; num = (num << 3) + (num << 1) + (c ^ '0'), c = getchar());
 31     return  up == '-' ? -num : num;
 32 }
 33 
 34 int n;
 35 int cntE, cntT;
 36 char s[inf];
 37 int mem[inf];
 38 int top[inf];
 39 int fa[inf];
 40 int son[inf];
 41 int size[inf];
 42 int dep[inf];
 43 int id[inf];
 44 int val[inf];
 45 int head[inf << 1];
 46 struct Edge{
 47     int to;
 48     int val;
 49     int next;
 50 }e[inf << 1];
 51 struct Tree{
 52     int l;
 53     int r;
 54     int max;
 55 }t[inf << 2];
 56 std::pair <int, int> p[inf];
 57 #define lson(a) (a) << 1
 58 #define rson(a) (a) << 1 | 1
 59 
 60 using std::max;
 61 
 62 inline void updata(int now){
 63     t[now].max = max (t[lson(now)].max , t[rson(now)].max);
 64     return;
 65 }
 66 
 67 void build(int now, int l, int r){
 68     t[now].l = l;
 69     t[now].r = r;
 70     if(l == r){
 71         t[now].max = val[l];
 72         return;
 73     }
 74     int mid = (l + r) >> 1;
 75     build(lson(now), l, mid);
 76     build(rson(now), mid + 1, r);
 77     updata(now);
 78     return;
 79 }
 80 
 81 inline void SgChange(int now, int x, int k){
 82     if(t[now].l > x || t[now].r < x)
 83         return;
 84     if(t[now].l == t[now].r){
 85         t[now].max = k; 
 86         return;
 87     }
 88     int mid = (t[now].l + t[now].r) >> 1;
 89     if(x <= mid)
 90         SgChange(lson(now), x, k);
 91     else 
 92         SgChange(rson(now), x, k);
 93     updata(now);
 94     return;
 95 }
 96 
 97 int SgQuery(int now, int l, int r){
 98     if(t[now].l >= l && t[now].r <= r)
 99         return t[now].max;
100     int mid = (t[now].l + t[now].r) >> 1;
101     int lmax = -INF;
102     int rmax = -INF;
103     if(l <= mid)
104         lmax = SgQuery(lson(now), l, r);
105     if(r > mid)
106         rmax = SgQuery(rson(now), l, r);
107     return max (lmax, rmax);
108 }
109 
110 inline int query(int a, int b){
111     int ans = -INF;
112     while(top[a] ^ top[b]){
113         if(dep[top[a]] < dep[top[b]])
114             std::swap(a, b);
115         ans = max (ans , SgQuery(1, id[top[a]], id[a]));
116         a = fa[top[a]];
117     }
118     if(a == b)
119         return ans;
120     if(dep[a] > dep[b])
121         std::swap(a, b);
122     ans = max (ans , SgQuery(1, id[a] + 1, id[b]));
123     return ans;
124 }
125 
126 inline int getVal(int now){
127     if(mem[now])
128         return mem[now];
129     for(int i = head[now]; i; i = e[i].next){
130         if(e[i].to == fa[now])
131             return mem[now] = e[i].val;
132     }
133     return mem[now] = -INF;
134 }
135 
136 void Dfs1(int now, int f, int depth){
137     fa[now] = f;
138     dep[now] = depth;
139     size[now] = 1;
140     int heavy = -INF;
141     for(int i = head[now]; i; i = e[i].next){
142         int to = e[i].to;
143         if(to == f)
144             continue;
145         Dfs1(to, now, depth + 1);
146         size[now] += size[to];
147         if(size[to] > heavy){
148             heavy = size[to];
149             son[now] = to;
150         }
151     }
152     return;
153 }
154 
155 void Dfs2(int now, int point){
156     ++cntT;
157     id[now] = cntT;
158     top[now] = point;
159     val[cntT] = (now == 1 ? -INF : getVal(now));
160     if(son[now] == 0)
161         return;
162     Dfs2(son[now], point);
163     for(int i = head[now]; i; i = e[i].next){
164         int to = e[i].to;
165         if(to == fa[now] || to == son[now])
166             continue;
167         Dfs2(to, to);
168     }
169     return;
170 }
171 
172 inline void AddEdge(int from, int to, int val){
173     ++cntE;
174     e[cntE].to = to;
175     e[cntE].val = val;
176     e[cntE].next = head[from];
177     head[from] = cntE;
178     return;
179 }
180 
181 inline int main(){
182     n = read();
183     for(int i = 1; i < n; i++){
184         int u = read();
185         int v = read();
186         int w = read();
187         AddEdge(u, v, w);
188         AddEdge(v, u, w);
189         p[i].first = u;
190         p[i].second = v;
191     }
192     Dfs1(1, 0, 1);
193     Dfs2(1, 1);
194     build(1, 1, n);
195     while(true){
196         scanf("%s", s + 1);
197         if(s[1] == 'D')
198             break;
199         int a = read();
200         int b = read();
201         if(s[1] == 'C'){
202             if(fa[p[a].first] == p[a].second)
203                 SgChange(1, id[p[a].first], b);
204             else 
205                 SgChange(1, id[p[a].second], b);
206         }
207         if(s[1] == 'Q'){
208             if(a == b)
209                 puts("0");
210             else printf("%d\n", query(a, b));
211         }
212     }
213     return 0;
214 }
215 
216 }//namespace chino
217 
218 int main(){return chino::main();}

题目2

注:这道题不能交C++

所以需要把C++改成C

  1 #include<math.h>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<stdlib.h>
  5 #define APART puts("----------------------")
  6 #define debug 1
  7 #define FILETEST 1
  8 #define inf 100010
  9 #define ll long long
 10 #define ha 998244353
 11 #define INF 0x7fffffff
 12 #define INF_T 9223372036854775807
 13 #define DEBUG printf("%s %d\n",__FUNCTION__,__LINE__)
 14 
 15 void setting(){
 16 #if FILETEST
 17     freopen("_test.in", "r", stdin);
 18     freopen("_test.me.out", "w", stdout);
 19 #endif
 20     return;
 21 }
 22 
 23 int read(){
 24     char c = getchar(), up = c; int num = 0;
 25     for(; c < '0' || c > '9'; up = c, c = getchar());
 26     for(; c >= '0' && c <= '9'; num = (num << 3) + (num << 1) + (c ^ '0'), c = getchar());
 27     return  up == '-' ? -num : num;
 28 }
 29 
 30 int n;
 31 int cntE, cntT;
 32 char s[inf];
 33 int head[inf];
 34 int top[inf];
 35 int mem[inf];
 36 int dep[inf];
 37 int fa[inf];
 38 int val[inf];
 39 int id[inf];
 40 int son[inf];
 41 int size[inf];
 42 struct Edge{
 43     int to;
 44     int val;
 45     int next;
 46 }e[inf << 1];
 47 struct Tree{
 48     int l;
 49     int r;
 50     int max; 
 51 }t[inf << 2];
 52 struct point{
 53     int first;
 54     int second;
 55 }p[inf];
 56 #define lson(a) (a) << 1
 57 #define rson(a) (a) << 1 | 1
 58 
 59 void AddEdge(int from, int to, int val){
 60     ++cntE;
 61     e[cntE].to = to;
 62     e[cntE].val = val;
 63     e[cntE].next = head[from];
 64     head[from] = cntE;
 65     return; 
 66 }
 67 
 68 int getVal(int now){
 69     if(mem[now])
 70         return mem[now];
 71     for(int i = head[now]; i; i = e[i].next){
 72         if(e[i].to == fa[now])
 73             return mem[now] = e[i].val;
 74     }
 75     return mem[now] = -INF;
 76 }
 77 
 78 void Dfs1(int now, int f, int depth){
 79     fa[now] = f;
 80     dep[now] = depth;
 81     size[now] = 1;
 82     int heavy = -INF;
 83     for(int i = head[now]; i; i = e[i].next){
 84         int to = e[i].to;
 85         if(to == f)
 86             continue;
 87         Dfs1(to, now, depth + 1);
 88         size[now] += size[to];
 89         if(heavy < size[to]){
 90             heavy = size[to];
 91             son[now] = to;
 92         }
 93     }
 94     return;
 95 }
 96 
 97 void Dfs2(int now, int point){
 98     ++cntT;
 99     id[now] = cntT;
100     val[cntT] = (now == 1 ? -INF : getVal(now));
101     top[now] = point;
102     if(son[now] == 0)
103         return;
104     Dfs2(son[now], point);
105     for(int i = head[now]; i; i = e[i].next){
106         int to = e[i].to;
107         if(to == fa[now] || to == son[now])
108             continue;
109         Dfs2(to, to);
110     }
111     return;
112 }
113 
114 int max(int a, int b){return a < b ? b : a;}
115 
116 #define swap(a, b) \
117     {\
118         int t = a;\
119         a = b;\
120         b = t;\
121     }
122 
123 void updata(int now){
124     t[now].max = max (t[lson(now)].max,  t[rson(now)].max);
125     return;
126 }
127 
128 void build(int now, int l, int r){
129     t[now].l = l;
130     t[now].r = r;
131     if(l == r){
132         t[now].max = val[l];
133         return;
134     }
135     int mid = (l + r) >> 1;
136     build(lson(now), l, mid);
137     build(rson(now), mid + 1, r);
138     updata(now);
139     return;
140 }
141 
142 void SgChange(int now, int x, int k){
143     if(t[now].l > x || t[now].r < x)
144         return;
145     if(t[now].l == t[now].r){
146         t[now].max = k;
147         return;
148     }
149     int mid = (t[now].l + t[now].r) >> 1;
150     if(x <= mid)
151         SgChange(lson(now), x, k);
152     else 
153         SgChange(rson(now), x, k);
154     updata(now);
155     return;
156 }
157 
158 int SgQuery(int now, int l, int r){
159     if(t[now].l >= l && t[now].r <= r)
160         return t[now].max;
161     int mid = (t[now].l + t[now].r) >> 1;
162     int Max = -INF;
163     if(l <= mid)
164         Max = max (Max, SgQuery(lson(now), l, r));
165     if(r > mid)
166         Max = max (Max, SgQuery(rson(now), l, r));
167     return Max;
168 }
169 
170 int query(int a, int b){
171     int ans = 0;
172     while(top[a] != top[b]){
173         if(dep[top[a]] < dep[top[b]])
174             swap(a, b);
175         ans = max (ans, SgQuery(1, id[top[a]], id[a]));
176         a = fa[top[a]];
177     }
178     if(a == b)
179         return ans;
180     if(dep[a] > dep[b])
181         swap(a, b);
182     ans = max (ans, SgQuery(1, id[a] + 1, id[b]));
183     return ans;
184 }
185 
186 void clear(){
187     memset(head, 0, sizeof head);
188     memset(size, 0, sizeof size);
189     memset(val, 0, sizeof val);
190     memset(mem, 0, sizeof mem);
191     memset(son, 0, sizeof son);
192     memset(top, 0, sizeof top);
193     memset(dep, 0, sizeof dep);
194     memset(id, 0, sizeof id);
195     memset(t, 0, sizeof t);
196     memset(e, 0, sizeof e);
197     memset(p, 0, sizeof p);
198     cntE = cntT = 0;
199     return;
200 }
201 
202 main(){
203     int T = read();
204 while(T--){
205     clear();
206     n = read();
207     for(int i = 1; i < n; i++){
208         int u = p[i].first = read();
209         int v = p[i].second = read();
210         int w = read();
211         AddEdge(u, v, w);
212         AddEdge(v, u, w);
213     }
214     Dfs1(1, 0, 1);
215     Dfs2(1, 1);
216     build(1, 1, n);
217     for(;;){
218         scanf("%s", s + 1);
219         if(s[1] == 'D')
220             break;
221         int a = read();
222         int b = read();
223         if(s[1] == 'Q'){
224             if(a == b)
225                 puts("0");
226             else printf("%d\n", query(a, b));
227         } else {
228             if(fa[p[a].first] == p[a].second)
229                 SgChange(1, id[p[a].first], b);
230             else 
231                 SgChange(1, id[p[a].second],b);
232         }
233     }
234 }
235     return 0;
236 }

 

posted @ 2019-09-30 21:30  ChiaroShiro  阅读(303)  评论(0编辑  收藏  举报