bzoj 1858 序列操作 线段树

传送门:

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

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<n)表示对于区间[a, b]执行标号为op的操作="" <="" div="" style="font-family: arial, verdana, helvetica, sans-serif;">

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




不错的线段树模板题

马丹,因为多打了个等号调了半个小时~~~~~省选可不要犯这种低级错误啊啊啊啊!!!!

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
#include<iostream>

#define MAXN 100010


using namespace std;


struct segment
{
    int from,to,l1,l0,r1,r0,m1,m0,sum,lazy;
} s[MAXN*4];
int oper,a[MAXN];
void update(int p)
{
    int l=p<<1,r=l+1;
    if(s[l].to-s[l].from==s[l].l1)
        s[p].l1=s[l].l1+s[r].l1;
    else
        s[p].l1=s[l].l1;
    if(s[r].to-s[r].from==s[r].r1)
        s[p].r1=s[r].r1+s[l].r1;
    else
        s[p].r1=s[r].r1;

    if(s[l].to-s[l].from==s[l].l0)
        s[p].l0=s[l].l0+s[r].l0;
    else
        s[p].l0=s[l].l0;
    if(s[r].to-s[r].from==s[r].r0)
        s[p].r0=s[r].r0+s[l].r0;
    else
        s[p].r0=s[r].r0;

    s[p].m1=max(s[l].r1+s[r].l1,max(s[l].m1,s[r].m1));
    s[p].m0=max(s[l].r0+s[r].l0,max(s[l].m0,s[r].m0));
    s[p].sum=s[l].sum+s[r].sum;
}
void push_down(int p)
{
    if(s[p].from+1==s[p].to) return;
    int l=p<<1,r=(p<<1)+1;
    if(s[p].lazy==3&&s[l].lazy) push_down(l);
    if(s[p].lazy==3&&s[r].lazy) push_down(r);
    s[l].lazy=s[r].lazy=s[p].lazy;
    if(s[p].lazy==1)
    {
        s[l].l0=s[l].r0=s[l].m0=s[l].to-s[l].from;
        s[l].l1=s[l].r1=s[l].m1=s[l].sum=0;
        s[r].l0=s[r].r0=s[r].m0=s[r].to-s[r].from;
        s[r].l1=s[r].r1=s[r].m1=s[r].sum=0;
    }
    else if(s[p].lazy==2)
    {
        s[l].l1=s[l].r1=s[l].m1=s[l].sum=s[l].to-s[l].from;
        s[l].r0=s[l].l0=s[l].m0=0;
        s[r].l1=s[r].r1=s[r].m1=s[r].sum=s[r].to-s[r].from;
        s[r].r0=s[r].l0=s[r].m0=0;
    }
    else
    {
        swap(s[l].r0,s[l].r1);
        swap(s[l].l0,s[l].l1);
        swap(s[l].m0,s[l].m1);
        s[l].sum=s[l].to-s[l].from-s[l].sum;

        swap(s[r].r0,s[r].r1);
        swap(s[r].l0,s[r].l1);
        swap(s[r].m0,s[r].m1);
        s[r].sum=s[r].to-s[r].from-s[r].sum;
    }
    s[p].lazy=0;
}
void build(int from,int to,int x)
{
    s[x].from=from;
    s[x].to=to;
    if(from+1==to)
    {
        if(a[from])
            s[x].l1=s[x].r1=s[x].sum=s[x].m1=1;
        else
            s[x].l0=s[x].r0=s[x].m0=1;
    }
    else
    {
        int mid=(from+to)>>1;
        build(from,mid,x<<1);
        build(mid,to,(x<<1)+1);
        update(x);
    }
}



void change(int from,int to,int x)
{
    if(s[x].lazy)
        push_down(x);
    if(s[x].from==from&&s[x].to==to)
    {
        if(oper==3)
        {
            s[x].sum=to-from-s[x].sum;
            swap(s[x].l1,s[x].l0);
            swap(s[x].r1,s[x].r0);
            swap(s[x].m1,s[x].m0);
            s[x].lazy=3;
        }
        else if(oper==2)
        {
            s[x].sum=s[x].m1=s[x].l1=s[x].r1=to-from;
            s[x].m0=s[x].l0=s[x].r0=0;
            s[x].lazy=2;
        }
        else if(oper==1)
        {
            s[x].sum=s[x].m1=s[x].l1=s[x].r1=0;
            s[x].m0=s[x].l0=s[x].r0=to-from;
            s[x].lazy=1;
        }
        return ;
    }
    int mid=(s[x].to+s[x].from)>>1;
    if(to<=mid)
        change(from,to,x<<1);
    else if(from>=mid)
        change(from,to,(x<<1)+1);
    else
    {
        change(from,mid,x<<1);
        change(mid,to,(x<<1)+1);
    }
    update(x);
}

int query(int from,int to,int p)
{
    if(s[p].lazy)
        push_down(p);
    if(s[p].from==from&&s[p].to==to)
        return s[p].sum;
    int mid=s[p].from+s[p].to>>1;
    if(to<=mid)
        return query(from,to,p<<1);
    else if(from>=mid)
        return query(from,to,(p<<1)+1);
    return query(from,mid,p<<1)+query(mid,to,(p<<1)+1);
}


segment query2(int from,int to,int p)
{
    if(s[p].lazy)
        push_down(p);
    if(s[p].from==from&&s[p].to==to)
        return s[p];
    int mid=s[p].from+s[p].to>>1;
    if(to<=mid)
        return query2(from,to,p<<1);
    else if(from>=mid)
        return query2(from,to,(p<<1)+1);
    segment temp,temp2,temp3;
    temp=query2(from,mid,p<<1);
    temp2=query2(mid,to,(p<<1)+1);
    if(temp.l1==temp.to-temp.from)
        temp3.l1=temp.l1+temp2.l1;
    else
        temp3.l1=temp.l1;
    if(temp2.r1==temp2.to-temp2.from)
        temp3.r1=temp2.r1+temp.r1;
    else
        temp3.r1=temp2.r1;
    temp3.m1=max(temp.r1+temp2.l1,max(temp.m1,temp2.m1));
    return temp3;
}

int main()
{
    int n,q,from,to,o;
    cin>>n>>q;
    for(int i=1; i<=n; i++)
        scanf("%d",&a[i]);
    build(1,n+1,1);
    int i;
    for(i=1; i<=q; i++)
    {
        scanf("%d%d%d",&o,&from,&to);
        from++,to++;
        if(o==0)
        {
            oper=1;
            change(from,to+1,1);
        }
        else if(o==1)
        {
            oper=2;
            change(from,to+1,1);
        }
        else if(o==2)
        {
            oper=3;
            change(from,to+1,1);
        }
        else if(o==3)
            printf("%d\n",query(from,to+1,1));
        else
            printf("%d\n",query2(from,to+1,1).m1);
    }
    return 0;

}

省选 rp++  bless me~~~~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值