BZOJ1858 [Scoi2010]序列操作

2 篇文章 0 订阅
2 篇文章 0 订阅

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
 

调试了半天 变量名打错了。。。

维护区间连续的数 类似于维护最大子段和   一下需要10个名字较长的变量把我整乱了。。。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100000+50;
int n,m,a[N];
struct point{int ls,rs,lazy,inv,cnt,sum,lsum,rsum,sum0,lsum0,rsum0;}t[4*N];
inline void print(point i)
 {printf("  %d %d %d %d %d %d %d %d %d\n\n",i.ls,i.rs,i.cnt,i.sum,i.lsum,i.rsum,i.sum0,i.lsum0,i.rsum0);
  //printf("  %d %d %d %d %d %d\n\n",i.ls,i.rs,i.cnt,i.sum,i.lsum,i.rsum);
 }
inline void pushup(int i)
  {t[i].cnt=t[2*i].cnt+t[2*i+1].cnt;
   
   t[i].lsum=t[2*i].lsum; 
   if(t[2*i].lsum==(t[2*i].rs-t[2*i].ls+1)) t[i].lsum+=t[2*i+1].lsum;
   t[i].rsum=t[2*i+1].rsum;               
   if(t[2*i+1].rsum==(t[2*i+1].rs-t[2*i+1].ls+1)) t[i].rsum+=t[2*i].rsum;
    
   t[i].sum=max(t[2*i].rsum+t[2*i+1].lsum
           ,max(max(t[i].lsum,t[i].rsum)
           ,max(t[2*i].sum,t[2*i+1].sum))); 
    
    
   t[i].lsum0=t[2*i].lsum0; 
   if(t[2*i].lsum0==t[2*i].rs-t[2*i].ls+1) t[i].lsum0+=t[2*i+1].lsum0;
   t[i].rsum0=t[2*i+1].rsum0; 
   if(t[2*i+1].rsum0==t[2*i+1].rs-t[2*i+1].ls+1) t[i].rsum0+=t[2*i].rsum0;
    
   t[i].sum0=max(t[2*i].rsum0+t[2*i+1].lsum0
            ,max(max(t[i].lsum0,t[i].rsum0)
            ,max(t[2*i].sum0,t[2*i+1].sum0)));    
  }
inline void pass(int i,int x)
  {
    t[i].lazy=x; t[i].inv=0; 
    t[i].cnt=t[i].sum=x*(t[i].rs-t[i].ls+1); t[i].sum0=(1-x)*(t[i].rs-t[i].ls+1);
    if(x==0)      {t[i].lsum=t[i].rsum=0; 
                   t[i].lsum0=t[i].rsum0=t[i].rs-t[i].ls+1;
                  }
    else if(x==1) {t[i].lsum0=t[i].rsum0=0; 
                   t[i].lsum=t[i].rsum=t[i].rs-t[i].ls+1;
                  }
  } 
inline void fan(int i)
  {  if(t[i].lazy!=-1) {pass(i,t[i].lazy^1); return;}
     t[i].inv^=1; 
     t[i].cnt=t[i].rs-t[i].ls+1-t[i].cnt;
     swap(t[i].lsum,t[i].lsum0);
     swap(t[i].rsum,t[i].rsum0);
     swap(t[i].sum,t[i].sum0);
  }   
inline void pushdown(int i)
  {if(t[i].lazy!=-1)
    {pass(2*i,t[i].lazy);
     pass(2*i+1,t[i].lazy);     
     t[i].lazy=-1;  
    }
     
   if(t[i].inv==1)  
    { t[i].inv=0;
      fan(2*i); fan(2*i+1);
    }
  }  
void build(int i,int l,int r)
 {t[i].ls=l; t[i].rs=r; t[i].lazy=-1; 
  if(l==r) {t[i].cnt=t[i].sum=t[i].lsum=t[i].rsum=a[l]; 
            t[i].sum0=t[i].lsum0=t[i].rsum0=1-a[l]; 
             return  ;
           }    
  int mid=t[i].ls+t[i].rs>>1;
  build(i<<1,l,mid); build(2*i+1,mid+1,r);
  pushup(i);
 }
void change(int i,int l,int r,int x)
 {if(l<=t[i].ls && t[i].rs<=r) {pass(i,x); return;}
  
  pushdown(i); int mid=t[i].ls+t[i].rs>>1;
  if(l<=mid) change(2*i,l,r,x);
  if(mid<r)  change(2*i+1,l,r,x);
  pushup(i);    
 }
void rev(int i,int l,int r)
 {if(l<=t[i].ls && t[i].rs<=r) {fan(i); return;}
  
  pushdown(i); int mid=t[i].ls+t[i].rs>>1;
  if(l<=mid) rev(2*i,l,r);
  if(mid<r)  rev(2*i+1,l,r);
  pushup(i);    
 } 
int ask(int i,int l,int r)
 {if(l<=t[i].ls && t[i].rs<=r) {return t[i].cnt;}
   
  pushdown(i); int mid=t[i].ls+t[i].rs>>1; //print(i);
  if(r<=mid) return ask(2*i,l,r);
  else if(mid<l)return ask(2*i+1,l,r);
  else          return ask(2*i,l,r)+ask(2*i+1,l,r);
 }  
point hehe(int i,int l,int r)
 {if(l<=t[i].ls && t[i].rs<=r) return t[i];
  
  pushdown(i); int mid=t[i].ls+t[i].rs>>1;
  
  if(r<=mid) return hehe(2*i,l,r);
  else if(mid<l)return hehe(2*i+1,l,r);
  else          {point r1=hehe(2*i,l,r),r2=hehe(2*i+1,l,r),re;
                  
                  re.cnt=r1.cnt+r2.cnt; re.ls=r1.ls; re.rs=r2.rs;
   
                   re.lsum=r1.lsum; 
                   if(r1.lsum==r1.rs-r1.ls+1) re.lsum+=r2.lsum;
                   re.rsum=r2.rsum;
                   if(r2.rsum==r2.rs-r2.ls+1) re.rsum+=r1.rsum;
                    
                   re.sum=max(r1.rsum+r2.lsum,max(max(re.lsum,re.rsum),max(r1.sum,r2.sum))); 
                  return re;
                }
 }   
void shuchu(int i)
 {if(t[i].ls==t[i].rs) {print(t[i]); return;}
 
  pushdown(i); print(t[i]);
  shuchu(2*i); shuchu(2*i+1);
 } 
void que(int i)
  {if(t[i].ls==t[i].rs) {printf("%d ",t[i].cnt);return;}
  pushdown(i); 
  que(2*i); que(2*i+1);
 } 
inline int read()
{   int k=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9')k=k*10+ch-'0',ch=getchar();
    return k*f;
} 
int main()
{
 scanf("%d%d",&n,&m);   int op,x,y;
 
 for(int i=1;i<=n;i++) a[i]=read();
 build(1,1,n); // shuchu(1);
 //print(t[1]);
  
 while(m--) 
  {op=read(); x=read(); y=read(); x++,y++;
   
   if(op==0)
     { change(1,x,y,0); //shuchu(1); printf("\n\n\n");
     }
   else if(op==1)
     { change(1,x,y,1); //shuchu(1); printf("\n\n\n");
     }
   else if(op==2)
     { rev(1,x,y);      //shuchu(1); printf("\n\n\n");
     }
   else if(op==3)  
     { printf("%d\n",ask(1,x,y));// shuchu(1); printf("\n\n\n");
     }
   else if(op==4)
     { //que(1); printf("\n\n\n");
       point ans=hehe(1,x,y); 
       printf("%d\n",ans.sum);// shuchu(1); printf("\n\n\n");
     }  
  }
return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值