码迷,mamicode.com
首页 > 其他好文 > 详细

1858: [Scoi2010]序列操作

时间:2016-04-29 22:02:11      阅读:136      评论:0      收藏:0      [点我收藏+]

标签:

1858: [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<n)表示对于区间[a, b]执行标号为op的操作="" <="" div="">

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

题解:

其实是蛮简单的一道题(不说了,我交了不下10次。。)

我们需要在维护一些关于0的量,对于2这个操作,其实就是交换0和1的量。。。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
#define p1 (p<<1)
#define p2 (p<<1|1)
int n,m,i,p,x,y;
int a[100005],t[400005],tl[400005];
int tmid[400005],tr[400005],add[400005];
int T[400005],Tmid[400005],Tr[400005],Tl[400005];
int ans[15];
void build(int l,int r,int p)
{
     if(l==r)
     {
         add[p]=a[l];
         tmid[p]=tl[p]=tr[p]=t[p]=a[l];
         Tmid[p]=Tl[p]=Tr[p]=T[p]=1-a[l];
         return;
     }
     int mid=(l+r)>>1;
     build(l,mid,p1);
     build(mid+1,r,p2);
     t[p]=t[p1]+t[p2];
     if(t[p1]==mid-l+1) tl[p]=tl[p1]+tl[p2];else tl[p]=tl[p1];
     if(t[p2]==r-mid) tr[p]=tr[p2]+tr[p1];else tr[p]=tr[p2];
     tmid[p]=max(tmid[p1],tmid[p2]);
     tmid[p]=max(tmid[p],tr[p1]+tl[p2]);
     T[p]=T[p1]+T[p2];
     if(T[p1]==mid-l+1) Tl[p]=Tl[p1]+Tl[p2];else Tl[p]=Tl[p1];
     if(T[p2]==r-mid) Tr[p]=Tr[p2]+Tr[p1];else Tr[p]=Tr[p2];
     Tmid[p]=max(Tmid[p1],Tmid[p2]);
     Tmid[p]=max(Tmid[p],Tr[p1]+Tl[p2]);
}
void update(int l,int r,int x,int y,int z,int p)
{
     if(x<=l&&r<=y)
     {
          if(z==0)
          {
              add[p]=0;
              T[p]=Tmid[p]=Tr[p]=Tl[p]=r-l+1;
              t[p]=tmid[p]=tr[p]=tl[p]=0;
          } else
          if(z==1)
          {
              add[p]=1;
              T[p]=Tmid[p]=Tr[p]=Tl[p]=0;
              t[p]=tmid[p]=tr[p]=tl[p]=r-l+1;
          } else
          if(z==2)
          {
              swap(t[p],T[p]);
              swap(tl[p],Tl[p]);
              swap(tr[p],Tr[p]);
              swap(tmid[p],Tmid[p]);
              add[p]=1-add[p];
          }
          return;
     }
     int mid=(l+r)>>1;
     if(add[p]!=-1)
     {
           update(l,mid,l,mid,add[p],p1);
           update(mid+1,r,mid+1,r,add[p],p2);
           add[p]=-1;
     }
     if(x<=mid) update(l,mid,x,y,z,p1);
     if(y>mid) update(mid+1,r,x,y,z,p2);
     t[p]=t[p1]+t[p2];
     if(t[p1]==mid-l+1) tl[p]=tl[p1]+tl[p2];else tl[p]=tl[p1];
     if(t[p2]==r-mid) tr[p]=tr[p2]+tr[p1];else tr[p]=tr[p2];
     tmid[p]=max(tmid[p1],tmid[p2]);
     tmid[p]=max(tmid[p],tr[p1]+tl[p2]);
     T[p]=T[p1]+T[p2];
     if(T[p1]==mid-l+1) Tl[p]=Tl[p1]+Tl[p2];else Tl[p]=Tl[p1];
     if(T[p2]==r-mid) Tr[p]=Tr[p2]+Tr[p1];else Tr[p]=Tr[p2];
     Tmid[p]=max(Tmid[p1],Tmid[p2]);
     Tmid[p]=max(Tmid[p],Tr[p1]+Tl[p2]);
}
void solve(int l,int r,int x,int y,int p,int X)
{
    if(x==l&&y==r)
    {
        ans[3]=max(ans[3],ans[4]+tl[p]);
        if(ans[1]==l-X) ans[2]+=tl[p];
        if(t[p]==r-l+1) ans[4]+=tr[p];else ans[4]=tr[p];
        ans[3]=max(ans[3],tmid[p]);
        ans[1]+=t[p];
        return;
    }
    int mid=(l+r)>>1;
    if(add[p]!=-1)
    {
        update(l,mid,l,mid,add[p],p1);
        update(mid+1,r,mid+1,r,add[p],p2);
        add[p]=-1;
    }
    if(y<=mid) solve(l,mid,x,y,p1,X);else
    if(x>mid) solve(mid+1,r,x,y,p2,X);else
    {
        solve(l,mid,x,mid,p1,X);
        solve(mid+1,r,mid+1,y,p2,X);
    }
    t[p]=t[p1]+t[p2];
    if(t[p1]==mid-l+1) tl[p]=tl[p1]+tl[p2];else tl[p]=tl[p1];
    if(t[p2]==r-mid) tr[p]=tr[p2]+tr[p1];else tr[p]=tr[p2];
    tmid[p]=max(tmid[p1],tmid[p2]);
    tmid[p]=max(tmid[p],tr[p1]+tl[p2]);
    T[p]=T[p1]+T[p2];
    if(T[p1]==mid-l+1) Tl[p]=Tl[p1]+Tl[p2];else Tl[p]=Tl[p1];
    if(T[p2]==r-mid) Tr[p]=Tr[p2]+Tr[p1];else Tr[p]=Tr[p2];
    Tmid[p]=max(Tmid[p1],Tmid[p2]);
    Tmid[p]=max(Tmid[p],Tr[p1]+Tl[p2]);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
    scanf("%d",&a[i]);
    memset(add,-1,sizeof(add));
    build(1,n,1);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%d",&p,&x,&y);
        x++;y++;
        if(p<=2)
        {
              update(1,n,x,y,p,1);
        } else
        {
              memset(ans,0,sizeof(ans));
              solve(1,n,x,y,1,x);
              if(p==3) printf("%d\n",ans[1]);else
              printf("%d\n",ans[3]);
        }
    }
    return 0;
}

 

1858: [Scoi2010]序列操作

标签:

原文地址:http://www.cnblogs.com/lwq12138/p/5447417.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!