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......)。
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具