P2572 [SCOI2010] 序列操作 (线段树)

P2572

又是一道颠覆我对线段树认知的题......

线段树每个节点维护八个信息:0/1个数,从左/右起0/1的个数,最长连续的0/1个数。

我们用线段树维护信息是需要区间合并的,因此为保证能够合并,我们才维护以上的八个信息。

打上两个标记:tg1={-1, 0, 1},-1表示没有,0表示将区间全部变成0,1表示将区间全部变成1;

tg2={0, 1},表示区间取反。

先上代码:

复制代码
 1 #include <bits/stdc++.h>
 2 #define mid ((l + r) >> 1)
 3 #define lc k << 1
 4 #define rc k << 1 | 1
 5 #define lson lc, l, mid
 6 #define rson rc, mid + 1, r
 7 using namespace std;
 8 int n, q, a[100001];
 9 struct node {
10     int w, b, lw, lb, rw, rb, mw, mb;
11     //构造函数,方便复制 
12     node(int w = 0, int b = 0, int lw = 0, int lb = 0, int rw = 0, int rb = 0, int mw = 0, int mb = 0) :
13     w(w), b(b), lw(lw), lb(lb), rw(rw), rb(rb), mw(mw), mb(mb){}    
14 }dat[262144];//维护复杂信息多使用结构体 
15 node merge(node i, node j) {//合并 
16     return node(
17         i.w + j.w, i.b + j.b,
18         (i.b ? i.lw : i.w + j.lw), (i.w ? i.lb : i.b + j.lb),
19         (j.b ? j.rw : j.w + i.rw), (j.w ? j.rb : j.b + i.rb),
20         max(max(i.mw, j.mw), i.rw + j.lw),
21         max(max(i.mb, j.mb), i.rb + j.lb));
22 }
23 int len[262144], tg1[262144], tg2[262144];
24 void build(int k, int l, int r) {
25     len[k] = r - l + 1, tg1[k] = -1;
26     if (l == r) {int t = a[l]; dat[k] = node(t, t ^ 1, t, t ^ 1, t, t ^ 1, t, t ^ 1); return ;}
27     build(lson), build(rson);
28     dat[k] = merge(dat[lc], dat[rc]);
29 }
30 void P(int k, int typ) {
31     node &t = dat[k];
32     //区间赋值为0 
33     if (typ == 0) tg2[k] = 0, tg1[k] = 0, t = node(0, len[k], 0, len[k], 0, len[k], 0, len[k]);
34     //区间赋值为1
35     if (typ == 1) tg2[k] = 0, tg1[k] = 1, t = node(len[k], 0, len[k], 0, len[k], 0, len[k], 0);
36     //区间取反
37     if (typ == 2) tg2[k] ^= 1, swap(t.w, t.b), swap(t.lw, t.lb), swap(t.rw, t.rb), swap(t.mw, t.mb);
38 }
39 void pd(int k) {//下传标记 
40     if (~tg1[k]) P(lc, tg1[k]), P(rc, tg1[k]);
41     if (tg2[k]) P(lc, 2), P(rc, 2);
42     tg1[k] = -1, tg2[k] = 0;
43 }
44 void Mdf(int k, int l, int r, int L, int R, int t) {
45     if (R < l || L > r) return ;//!!!!!!!
46     if (L <= l && R >= r) {P(k, t); return ;}
47     pd(k);
48     Mdf(lson, L, R, t), Mdf(rson, L, R, t);
49     dat[k] = merge(dat[lc], dat[rc]);
50 }
51 node Qur(int k, int l, int r, int L, int R) {
52     if (R < l || L > r) return node();//!!!!!!!
53     if (L <= l && R >= r) return dat[k];
54     pd(k);
55     return merge(Qur(lson, L, R), Qur(rson, L, R));
56 }
57 int main() {
58     scanf("%d %d", &n, &q);
59     for (int i = 1; i <= n; i ++) scanf("%d", a + i);
60     build(1, 1, n);
61     while (q --) {
62         int opt, l, r;
63         scanf("%d %d %d", &opt, &l, &r); l ++, r ++;
64         if (opt < 3) Mdf(1, 1, n, l, r, opt);
65         else {node t = Qur(1, 1, n, l, r); printf("%d\n", opt == 3 ? t.w : t.mw);}
66     }
67     return 0;
68 }
复制代码

用结构体的构造函数可以大大减少代码量,建议维护复杂信息时都采用这种方式。

另外,代码第45,52行的操作加上最好(我没加上就一直RE......)。

巨佬博客



如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   YHXo  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示