P2572 [SCOI2010] 序列操作 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
思路不是很难,码量很大,调试难度高,一个bug找一天(bushi
稍微难一些的就是求[l,r] 区间内最多有多少个连续的 1,可以分别维护一段区间左端,中间,右端有多少个连续的1和0来实现。同时要注意的点是赋0和赋1标记可以覆盖取反标记,而取反标记不能覆盖赋0和赋1标记,而且取反标记更改时要^=1
具体看代码注释
- #include
- using namespace std;
- #define INF 0x3f3f3f3f
- #define INF_L 0x3f3f3f3f3f3f3f3fLL
- #define NOTLE ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
- #define endl '\n'
- #define T int TT;cin >> TT;while (TT--)
- #define lint long long
- #define PII pair
- #define PLL pair
- #define pb push_back
- #define eb emplace_back
- int a[100010];
- int n,m;
- struct node{
- int l,r,sum;
- int sw,t0,t1; //sw取反标记,t0赋0标记,t1赋1标记
- int ll1,lm1,lr1,ll0,lm0,lr0;
- //ll1维护区间左端连续1的长度
- //lm1维护区间中间最长连续1的长度
- //lr1维护区间右端连续1的长度
- }tree[400010],node0;
-
- void pushup(int p){
- tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
-
- tree[p].ll1=tree[p<<1].ll1;
- tree[p].lr1=tree[p<<1|1].lr1;
- /*如果左或右端的连续1长度等于区间长度,则需要将另一段要合并的区间的左端或右端
- 的连续1长度加上*/
- if(tree[p<<1].ll1==tree[p<<1].r-tree[p<<1].l+1){
- tree[p].ll1+=tree[p<<1|1].ll1;
- }
- if(tree[p<<1|1].lr1==tree[p<<1|1].r-tree[p<<1|1].l+1){
- tree[p].lr1+=tree[p<<1].lr1;
- }
- tree[p].lm1=max(tree[p<<1].lr1+tree[p<<1|1].ll1,max(tree[p<<1].lm1,tree[p<<1|1].lm1));
-
- tree[p].ll0=tree[p<<1].ll0;
- tree[p].lr0=tree[p<<1|1].lr0;
- if(tree[p<<1].ll0==tree[p<<1].r-tree[p<<1].l+1){
- tree[p].ll0+=tree[p<<1|1].ll0;
- }
- if(tree[p<<1|1].lr0==tree[p<<1|1].r-tree[p<<1|1].l+1){
- tree[p].lr0+=tree[p<<1].lr0;
- }
- tree[p].lm0=max(tree[p<<1].lr0+tree[p<<1|1].ll0,max(tree[p<<1].lm0,tree[p<<1|1].lm0));
- }
- void pushdown(int p){
- if(tree[p].t0){
- tree[p<<1].t0=tree[p<<1|1].t0=1;
- tree[p<<1].t1=tree[p<<1|1].t1=0;
- tree[p<<1].sw=tree[p<<1|1].sw=0;
- tree[p<<1].sum=0;
- tree[p<<1].ll1=tree[p<<1].lm1=tree[p<<1].lr1=0;
- tree[p<<1].ll0=tree[p<<1].lm0=tree[p<<1].lr0=tree[p<<1].r-tree[p<<1].l+1;
- tree[p<<1|1].sum=0;
- tree[p<<1|1].ll1=tree[p<<1|1].lm1=tree[p<<1|1].lr1=0;
- tree[p<<1|1].ll0=tree[p<<1|1].lm0=tree[p<<1|1].lr0=tree[p<<1|1].r-tree[p<<1|1].l+1;
- }
- if(tree[p].t1){
- tree[p<<1].t0=tree[p<<1|1].t0=0;
- tree[p<<1].t1=tree[p<<1|1].t1=1;
- tree[p<<1].sw=tree[p<<1|1].sw=0;
- tree[p<<1].sum=tree[p<<1].r-tree[p<<1].l+1;
- tree[p<<1].ll1=tree[p<<1].lm1=tree[p<<1].lr1=tree[p<<1].r-tree[p<<1].l+1;
- tree[p<<1].ll0=tree[p<<1].lm0=tree[p<<1].lr0=0;
- tree[p<<1|1].sum=tree[p<<1|1].r-tree[p<<1|1].l+1;
- tree[p<<1|1].ll1=tree[p<<1|1].lm1=tree[p<<1|1].lr1=tree[p<<1|1].r-tree[p<<1|1].l+1;
- tree[p<<1|1].ll0=tree[p<<1|1].lm0=tree[p<<1|1].lr0=0;
- }
- if(tree[p].sw){
- tree[p<<1].sw^=1;
- tree[p<<1|1].sw^=1;
- tree[p<<1].sum=tree[p<<1].r-tree[p<<1].l+1-tree[p<<1].sum;
- swap(tree[p<<1].ll1,tree[p<<1].ll0);
- swap(tree[p<<1].lm1,tree[p<<1].lm0);
- swap(tree[p<<1].lr1,tree[p<<1].lr0);
- tree[p<<1|1].sum=tree[p<<1|1].r-tree[p<<1|1].l+1-tree[p<<1|1].sum;
- swap(tree[p<<1|1].ll1,tree[p<<1|1].ll0);
- swap(tree[p<<1|1].lm1,tree[p<<1|1].lm0);
- swap(tree[p<<1|1].lr1,tree[p<<1|1].lr0);
- }
- tree[p].t0=tree[p].t1=tree[p].sw=0;
- }
- void build(int l,int r,int p=1){
- tree[p].l=l,tree[p].r=r;
- tree[p].ll1=tree[p].lm1=tree[p].lr1=tree[p].ll0=tree[p].lm0=tree[p].lr0=0;
- tree[p].sw=tree[p].t0=tree[p].t1=0;
- if(l==r){
- tree[p].sum=a[l];
- if(a[l]) tree[p].ll1=tree[p].lm1=tree[p].lr1=1;
- else tree[p].ll0=tree[p].lm0=tree[p].lr0=1;
- return ;
- }
- int mid=l+r>>1;
- build(l,mid,p<<1);
- build(mid+1,r,p<<1|1);
- pushup(p);
- }
- void turn(int l,int r,int t,int p=1){ //赋值
- if(l<=tree[p].l && r>=tree[p].r){
- if(t==0){
- tree[p].t0=1,tree[p].t1=0;
- tree[p].sum=0;
- tree[p].ll1=tree[p].lm1=tree[p].lr1=0;
- tree[p].ll0=tree[p].lm0=tree[p].lr0=tree[p].r-tree[p].l+1;
- }
- else {
- tree[p].t0=0,tree[p].t1=1;
- tree[p].sum=tree[p].r-tree[p].l+1;
- tree[p].ll1=tree[p].lm1=tree[p].lr1=tree[p].r-tree[p].l+1;
- tree[p].ll0=tree[p].lm0=tree[p].lr0=0;
- }
- tree[p].sw=0;
- return ;
- }
- pushdown(p);
- int mid=tree[p].l+tree[p].r>>1;
- if(l<=mid) turn(l,r,t,p<<1);
- if(r>mid) turn(l,r,t,p<<1|1);
- pushup(p);
- }
- void swc(int l,int r,int p=1){ //取反
- if(l<=tree[p].l && r>=tree[p].r){
- tree[p].sum=tree[p].r-tree[p].l+1-tree[p].sum;
- swap(tree[p].ll1,tree[p].ll0);
- swap(tree[p].lm1,tree[p].lm0);
- swap(tree[p].lr1,tree[p].lr0);
- tree[p].sw^=1;
- return ;
- }
- pushdown(p);
- int mid=tree[p].l+tree[p].r>>1;
- if(l<=mid) swc(l,r,p<<1);
- if(r>mid) swc(l,r,p<<1|1);
- pushup(p);
- }
- int querysum(int l,int r,int p=1){ //询问区间1个数
- if(l<=tree[p].l && r>=tree[p].r) return tree[p].sum;
- pushdown(p);
- int mid=tree[p].l+tree[p].r>>1,sum=0;
- if(l<=mid) sum+=querysum(l,r,p<<1);
- if(r>mid) sum+=querysum(l,r,p<<1|1);
- return sum;
- }
- node queryl(int l,int r,int p=1){ //询问区间最长连续1
- if(l<=tree[p].l && r>=tree[p].r) return tree[p];
- pushdown(p);
- int mid=tree[p].l+tree[p].r>>1;
- node x=node0,lx=node0,rx=node0;
- int fl=0,fr=0;
- if(l<=mid){lx=queryl(l,r,p<<1); fl=1;}
- if(r>mid){rx=queryl(l,r,p<<1|1); fr=1;}
- if(fl+fr==2){
- x.ll1=lx.ll1;
- x.lr1=rx.lr1;
- if(lx.ll1==lx.r-lx.l+1){
- x.ll1+=rx.ll1;
- }
- if(rx.lr1==rx.r-rx.l+1){
- x.lr1+=lx.lr1;
- }
- x.lm1=max(lx.lr1+rx.ll1,max(lx.lm1,rx.lm1));
- }
- else if(fl==0) x=rx;
- else if(fr==0) x=lx;
- return x;
- }
- void init(){
- node0.ll1=node0.lm1=node0.lr1=node0.ll0=node0.lm0=node0.lr0=0;
- node0.sw=node0.t0=node0.t1=0;
- }
- int main(){
- NOTLE;
- init();
- cin >> n >> m;
- for(int i=1;i<=n;i++) cin >> a[i];
- build(1,n);
- for(int i=1;i<=m;i++){
- int opt,l,r;
- cin >> opt >> l >> r;
- l++,r++;
- if(opt==0){
- turn(l,r,0);
- }
- if(opt==1){
- turn(l,r,1);
- }
- if(opt==2){
- swc(l,r);
- }
- if(opt==3){
- cout << querysum(l,r) << endl;
- }
- if(opt==4){
- node x=queryl(l,r);
- cout << max(max(x.ll1,x.lr1),x.lm1) << endl;
- }
- }
- return 0;
- }
此题还有一种解法是珂朵莉树,但只能过随机的数据,无法通过洛谷上已经针对过的数据
- #include
- using namespace std;
- #define INF 0x3f3f3f3f
- #define INF_L 0x3f3f3f3f3f3f3f3fLL
- #define NOTLE ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
- #define endl '\n'
- #define T int TT;cin >> TT;while (TT--)
- #define lint long long
- #define PII pair
- #define PLL pair
- #define S_IT set
::iterator - #define pb push_back
- #define eb emplace_back
- #define MAXN 100002
-
- typedef int type;
- struct Node{
- unsigned int l;
- unsigned int r;
- mutable type data;
- Node(unsigned int a, unsigned int b = 0, type c = 0);
- bool operator <(const Node &a) const{return l < a.l;}
- };
- Node::Node(unsigned int a, unsigned int b, type c){l = a; r = b; data = c;}
- set
s; -
- S_IT split(unsigned int pos){
- S_IT it = s.lower_bound(Node(pos));
- if (it != s.end() && it->l == pos) return it;
- --it;
- unsigned int l = it->l, r = it->r;
- type data = it->data;
- s.erase(it);
- s.insert(Node(l, pos - 1, data));
- return s.insert(Node(pos, r, data)).first;
- }
-
- void swc(int l,int r,int val){
- S_IT it2 = split(r + 1), it1 = split(l);
- s.erase(it1, it2);
- s.insert(Node(l, r, val));
- return;
- }
-
- void rev(int l,int r){
- S_IT it2 = split(r + 1), it1 = split(l);
- for (; it1 != it2; ++it1)
- it1->data ^= 1;
- }
-
- int sum(int l,int r){
- S_IT it2 = split(r + 1), it1 = split(l);
- int res=0;
- for (; it1 != it2; ++it1)
- if(it1->data) res+=(it1->r)-(it1->l)+1;
- return res;
- }
-
- int con(int l,int r){
- int res=0,temp=0;
- S_IT it2 = split(r + 1), it1 = split(l);
- for (; it1 != it2; ++it1){
- if (it1->data){
- temp+=(it1->r)-(it1->l)+1;
- }
- else{
- res=max(res,temp);
- temp=0;
- }
- }
- return max(res, temp);
- }
-
- int main(){
- NOTLE;
- int n, m;
- cin >> n >> m;
- for (int i = 0; i < n; ++i){
- int temp;
- cin >> temp;
- s.insert(Node(i, i, temp));
- }
- s.insert(Node(n, n, 0));
- while(m--){
- int op,a,b;
- cin >> op >> a >> b;
- if (op==0) swc(a, b, 0);
- if (op==1) swc(a, b, 1);
- if (op==2) rev(a, b);
- if (op==3) cout << sum(a, b) << endl;
- if (op==4) cout << con(a, b) << endl;
- }
- return 0;
- }