• BZOJ1858: [Scoi2010]序列操作


    BZOJ1858: [Scoi2010]序列操作

    Description

    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都需要给出回答,聪明的程序员们,你们能帮助他吗?

    Input

    输入数据第一行包括2个数,n和m,分别表示序列的长度和操作数目

    第二行包括n个数,表示序列的初始状态

    接下来m行,每行3个数,op, a, b,(0 < = op < = 4,0 < = a < = b)

    Output

    对于每一个询问操作,输出一行,包括1个数,表示其对应的答案

    Sample Input

    10 10
    0 0 0 1 1 0 1 0 1 1
    1 0 2
    3 0 5
    2 2 2
    4 0 4
    0 3 6
    2 3 7
    4 2 8
    1 0 5
    0 5 6
    3 3 9

    Sample Output

    5
    2
    6
    5

    HINT

    对于30%的数据,1<=n, m<=1000

    对于100%的数据,1< = n, m < = 100000

    题解Here!

    看到 区间修改+区间查询。。。

    去吧,线段树。。。

    于是一个晚上就没了。。。

    恶心啊!!!

    线段树记录:

    区间和值;

    区间最长0、1的长度;

    从左端点开始最长0、1的长度,从右端点开始最长0、1的长度;

    两个标记:全赋0/1,取反;

    左右端点。

    3很好做,4呢?

    我们有一个O(nlogn)的分治算法,但是因为有O(n)的算法,前者就被我们抛弃了。。。

    这时候,它的强大就体现了出来!

    所以求4时,返回的不是一个值,而是一个线段树节点。

    修改时,若正在改某区间的 全赋0/1 标记,记得将 取反 标记清0,巨坑。。。

    还有上传,下传很重要,但是太恶心,不想多说,看代码吧。。。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define LSON rt<<1
    #define RSON rt<<1|1
    #define DATA(x) a[x].data
    #define SIGN1(x) a[x].c
    #define SIGN2(x) a[x].v
    #define SUM1(x) a[x].sum1
    #define SUM2(x) a[x].sum2
    #define LEFT1(x) a[x].left1
    #define LEFT2(x) a[x].left2
    #define RIGHT1(x) a[x].right1
    #define RIGHT2(x) a[x].right2
    #define LSIDE(x) a[x].l
    #define RSIDE(x) a[x].r
    #define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
    #define MAXN 100010
    using namespace std;
    int n,m;
    struct node{
        int data,c,v,left1,right1,sum1,left2,right2,sum2;
        int l,r;
    }a[MAXN<<2];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    void pushup(int rt){
        DATA(rt)=DATA(LSON)+DATA(RSON);
        SUM1(rt)=max(RIGHT1(LSON)+LEFT1(RSON),max(SUM1(LSON),SUM1(RSON)));
        SUM2(rt)=max(RIGHT2(LSON)+LEFT2(RSON),max(SUM2(LSON),SUM2(RSON)));
        LEFT1(rt)=LEFT1(LSON);RIGHT1(rt)=RIGHT1(RSON);
    	LEFT2(rt)=LEFT2(LSON);RIGHT2(rt)=RIGHT2(RSON);
        if(LEFT1(LSON)==WIDTH(LSON))LEFT1(rt)+=LEFT1(RSON);
        if(LEFT2(LSON)==WIDTH(LSON))LEFT2(rt)+=LEFT2(RSON);
        if(RIGHT1(RSON)==WIDTH(RSON))RIGHT1(rt)+=RIGHT1(LSON);
        if(RIGHT2(RSON)==WIDTH(RSON))RIGHT2(rt)+=RIGHT2(LSON);
    }
    void pushdown(int rt){
        if(LSIDE(rt)==RSIDE(rt))return;
        if(SIGN1(rt)!=-1){
            SIGN1(LSON)=SIGN1(rt);
    		SIGN2(LSON)=0;
            DATA(LSON)=SUM2(LSON)=LEFT2(LSON)=RIGHT2(LSON)=SIGN1(rt)*WIDTH(LSON);
            SUM1(LSON)=LEFT1(LSON)=RIGHT1(LSON)=(SIGN1(rt)^1)*WIDTH(LSON);
            SIGN1(RSON)=SIGN1(rt);
    		SIGN2(RSON)=0;
            DATA(RSON)=SUM2(RSON)=LEFT2(RSON)=RIGHT2(RSON)=SIGN1(rt)*WIDTH(RSON);
            SUM1(RSON)=LEFT1(RSON)=RIGHT1(RSON)=(SIGN1(rt)^1)*WIDTH(RSON);
            SIGN1(rt)=-1;
        }
        if(SIGN2(rt)){
            SIGN2(LSON)^=1;
            DATA(LSON)=WIDTH(LSON)-DATA(LSON);
            swap(SUM1(LSON),SUM2(LSON));
            swap(LEFT1(LSON),LEFT2(LSON));swap(RIGHT1(LSON),RIGHT2(LSON));
            SIGN2(RSON)^=1;
            DATA(RSON)=WIDTH(RSON)-DATA(RSON);
            swap(SUM1(RSON),SUM2(RSON));
            swap(LEFT1(RSON),LEFT2(RSON));swap(RIGHT1(RSON),RIGHT2(RSON));
            SIGN2(rt)=0;
        }
    }
    void buildtree(int l,int r,int rt){
        int mid;
        LSIDE(rt)=l;RSIDE(rt)=r;
        SIGN1(rt)=-1;SIGN2(rt)=0;
        if(l==r){
        	int x=read();
            DATA(rt)=LEFT2(rt)=RIGHT2(rt)=SUM2(rt)=x;
            LEFT1(rt)=RIGHT1(rt)=SUM1(rt)=x^1;
            return;
        }
        mid=l+r>>1;
        buildtree(l,mid,LSON);
        buildtree(mid+1,r,RSON);
        pushup(rt);
    }
    void update_all(int l,int r,int c,int rt){
        int mid;
        if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
            SIGN1(rt)=c;
            SIGN2(rt)=0;
            DATA(rt)=LEFT2(rt)=RIGHT2(rt)=SUM2(rt)=c*WIDTH(rt);
            LEFT1(rt)=RIGHT1(rt)=SUM1(rt)=(c^1)*WIDTH(rt);
            pushdown(rt);
            return;
        }
        pushdown(rt);
        mid=LSIDE(rt)+RSIDE(rt)>>1;
        if(l<=mid)update_all(l,r,c,LSON);
        if(mid<r)update_all(l,r,c,RSON);
        pushup(rt);
    }
    void update_false(int l,int r,int rt){
        int mid;
        if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
            SIGN2(rt)^=1;
            DATA(rt)=WIDTH(rt)-DATA(rt);
            swap(SUM1(rt),SUM2(rt));
            swap(LEFT1(rt),LEFT2(rt));swap(RIGHT1(rt),RIGHT2(rt));
            pushdown(rt);
            return;
        }
        pushdown(rt);
        mid=LSIDE(rt)+RSIDE(rt)>>1;
        if(l<=mid)update_false(l,r,LSON);
        if(mid<r)update_false(l,r,RSON);
        pushup(rt);
    }
    int query_all(int l,int r,int rt){
        int mid,ans=0;
        if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
        return DATA(rt);
        pushdown(rt);
        mid=LSIDE(rt)+RSIDE(rt)>>1;
        if(l<=mid)ans+=query_all(l,r,LSON);
        if(mid<r)ans+=query_all(l,r,RSON);
        return ans;
    }
    node query_length(int l,int r,int rt){
        int mid;
        if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
        return a[rt];
        pushdown(rt);
        mid=LSIDE(rt)+RSIDE(rt)>>1;
        node ans,ls,rs;
        ans=ls=rs=(node){0,0,0,0,0,0,0,0,0,0,0};
        if(l<=mid)ls=query_length(l,r,LSON);
        if(mid<r)rs=query_length(l,r,RSON);
        ans.sum1=max(ls.right1+rs.left1,max(ls.sum1,rs.sum1));
    	ans.sum2=max(ls.right2+rs.left2,max(ls.sum2,rs.sum2));
        ans.left1=ls.left1;ans.right1=rs.right1;
        ans.left2=ls.left2;ans.right2=rs.right2;
        if(ls.left1==WIDTH(LSON))ans.left1+=rs.left1;
        if(ls.left2==WIDTH(LSON))ans.left2+=rs.left2;
        if(rs.right1==WIDTH(RSON))ans.right1+=ls.right1;
        if(rs.right2==WIDTH(RSON))ans.right2+=ls.right2;
        return ans;
    }
    int main(){
        int f,x,y;
        n=read();m=read();
        buildtree(1,n,1);
        while(m--){
            f=read();x=read()+1;y=read()+1;
            switch(f){
                case 0:{
                    update_all(x,y,0,1);
                    break;
                }
                case 1:{
                    update_all(x,y,1,1);
                    break;
                }
                case 2:{
                    update_false(x,y,1);
                    break;
                }
                case 3:{
                    printf("%d
    ",query_all(x,y,1));
                    break;
                }
                case 4:{
                    node s=query_length(x,y,1);
                    printf("%d
    ",s.sum2);
                    break;
                }
            }
        }
    	return 0;
    }
    
  • 相关阅读:
    SVGEditor
    SVG六基本元素
    SVG在网页中的四种使用方式
    Chrome中java因过期而遭到阻止
    Weblogic常见故障常:JDBC Connection Pools
    MyBatis java.sql.SQLSyntaxErrorException: ORA-00911: 无效字符
    MYBATIS 无效的列类型: 1111
    [MyBatis]mapperLocations属性通配符的使用
    secureCRT自动化脚本
    google protocol buffer的原理和使用(四)
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/8997390.html
Copyright © 2020-2023  润新知