BZOJ1858:[SCOI2010]序列操作——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=1858

lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作:

0 a b 把[a, b]区间内的所有数全变成0

1 a b 把[a, b]区间内的所有数全变成1

2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0

3 a b 询问[a, b]区间内总共有多少个1

4 a b 询问[a, b]区间内最多有多少个连续的1

对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?

线段树嘛,很裸的,正好趁自己神志不清试着来写写吧。

woc这线段树真恶心,2个标记维护7个量!

显然需要维护区间1个数,区间最大连续1。

为了合并还需要维护区间左最大连续1和右最大连续1.

为了取反还需要把上述东西的0也给求出来。

之后你愉快的敲起了数组线段树,结果发现你4操作写起来贼费劲。

靠!改结构体!

然后就是两个标记纠缠不清的问题了。

于是过了三次拍,debug了三次,终于过了……

2h+考场直接gg。

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+5;
const int p=1e9+7;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct node{
    int l,r,ls0,rs0,ls1,rs1;
    int lz,sum,rng0,rng1;
    bool rev;
}t[N*4];
int n,m,b[N];
inline void upt(int a,int l,int r){
    int mid=(l+r)>>1,ls=a<<1,rs=a<<1|1;
    t[a].sum=t[ls].sum+t[rs].sum;
    t[a].rng1=max(t[ls].rs1+t[rs].ls1,max(t[ls].rng1,t[rs].rng1));
    t[a].rng0=max(t[ls].rs0+t[rs].ls0,max(t[ls].rng0,t[rs].rng0));
    t[a].ls1=t[ls].ls1+(t[ls].ls1==mid-l+1?t[rs].ls1:0);
    t[a].rs1=t[rs].rs1+(t[rs].rs1==r-mid?t[ls].rs1:0);
    t[a].ls0=t[ls].ls0+(t[ls].ls0==mid-l+1?t[rs].ls0:0);
    t[a].rs0=t[rs].rs0+(t[rs].rs0==r-mid?t[ls].rs0:0);
}
inline void turn(int a){
    t[a].sum=t[a].r-t[a].l+1-t[a].sum;
    swap(t[a].ls1,t[a].ls0);
    swap(t[a].rs1,t[a].rs0);
    swap(t[a].rng1,t[a].rng0);
}
inline void change(int a,int w){
    if(w){
    t[a].ls1=t[a].rs1=t[a].sum=t[a].rng1=t[a].r-t[a].l+1;
    t[a].ls0=t[a].rs0=t[a].rng0=0;
    }
    else{
    t[a].ls0=t[a].rs0=t[a].rng0=t[a].r-t[a].l+1;
    t[a].ls1=t[a].rs1=t[a].sum=t[a].rng1=0;
    }
    t[a].rev=0;
}
inline void push(int a){
    int ls=a<<1,rs=a<<1|1;
    if(t[a].lz!=-1){
    change(ls,t[a].lz);change(rs,t[a].lz);
    t[ls].lz=t[rs].lz=t[a].lz;t[a].lz=-1;
    }
    if(t[a].rev){
    turn(ls);turn(rs);
    t[ls].rev^=1;t[rs].rev^=1;t[a].rev=0;
    }
}
void build(int a,int l,int r){
    t[a].lz=-1;t[a].rev=0;t[a].l=l;t[a].r=r;
    if(l==r){
    t[a].sum=b[l];
    if(b[l])t[a].ls1=t[a].rs1=t[a].rng1=1;
    else t[a].ls0=t[a].rs0=t[a].rng0=1;
    return;
    }
    int mid=(l+r)>>1;
    build(a<<1,l,mid);build(a<<1|1,mid+1,r);
    upt(a,l,r);
}
void modify(int a,int l,int r,int l1,int r1,int w){
    if(r<l1||r1<l)return;
    if(l1<=l&&r<=r1){
    t[a].lz=w;change(a,w);
    return;
    }
    push(a);
    int mid=(l+r)>>1;
    modify(a<<1,l,mid,l1,r1,w);
    modify(a<<1|1,mid+1,r,l1,r1,w);
    upt(a,l,r);
}
void reverse(int a,int l,int r,int l1,int r1){
    if(r<l1||r1<l)return;
    if(l1<=l&&r<=r1){
    t[a].rev^=1;turn(a);
    return;
    }
    push(a);
    int mid=(l+r)>>1;
    reverse(a<<1,l,mid,l1,r1);
    reverse(a<<1|1,mid+1,r,l1,r1);
    upt(a,l,r);    
}
int query_sum(int a,int l,int r,int l1,int r1){
    if(r<l1||r1<l)return 0;
    if(l1<=l&&r<=r1)return t[a].sum;
    push(a);
    int mid=(l+r)>>1;
    return query_sum(a<<1,l,mid,l1,r1)+
    query_sum(a<<1|1,mid+1,r,l1,r1);
}
node query_rng(int a,int l,int r,int l1,int r1){
    if(l1==l&&r==r1)return t[a];
    push(a);
    int mid=(l+r)>>1;
    if(mid>=r1)return query_rng(a<<1,l,mid,l1,r1);
    else if(mid+1<=l1)return query_rng(a<<1|1,mid+1,r,l1,r1);
    node lans=query_rng(a<<1,l,mid,l1,mid);
    node rans=query_rng(a<<1|1,mid+1,r,mid+1,r1);
    node ans;
    ans.l=lans.l;ans.r=rans.r;
    ans.rng1=max(lans.rs1+rans.ls1,max(lans.rng1,rans.rng1));
    ans.rng0=max(lans.rs0+rans.ls0,max(lans.rng0,rans.rng0));
    ans.ls1=lans.ls1+(lans.ls1==mid-l+1?rans.ls1:0);
    ans.rs1=rans.rs1+(rans.rs1==r-mid?lans.rs1:0);
    ans.ls0=lans.ls0+(lans.ls0==mid-l+1?rans.ls0:0);
    ans.rs0=rans.rs0+(rans.rs0==r-mid?lans.rs0:0);
    return ans;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++)b[i]=read();
    build(1,1,n);
    while(m--){
    int op=read(),l=read()+1,r=read()+1;
    if(op==0)modify(1,1,n,l,r,0);
    if(op==1)modify(1,1,n,l,r,1);
    if(op==2)reverse(1,1,n,l,r);
    if(op==3)printf("%d\n",query_sum(1,1,n,l,r));
    if(op==4)printf("%d\n",query_rng(1,1,n,l,r).rng1);
    }
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

posted @ 2018-06-15 15:05  luyouqi233  阅读(187)  评论(0编辑  收藏  举报