#include<cstdio>
#include<iostream>
#define lc k<<1
#define rc k<<1|1
using namespace std;
const int N=1e5+;
int n,m,a[N];
struct sgt{
int sum,tag,rev,max1,max0,lss0,rss0,lss1,rss1,lp,rp,l,r;
}s,tr[N<<];
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
sgt merge(sgt left,sgt right){
sgt now;
now.lp=left.lp;
now.rp=right.rp;
now.sum=left.sum+right.sum; now.lss0=left.lss0;
now.rss0=right.rss0;
if(!right.lp&&!left.sum) now.lss0=max(now.lss0,left.r-left.l++right.lss0);
if(!left.rp&&!right.sum) now.rss0=max(now.rss0,right.r-right.l++left.rss0);
now.max0=max(left.max0,right.max0);
if(!left.rp&&!right.lp) now.max0=max(now.max0,left.rss0+right.lss0); now.lss1=left.lss1;
now.rss1=right.rss1;
if(right.lp&&left.sum==left.r-left.l+) now.lss1=max(now.lss1,left.sum+right.lss1);
if(left.rp&&right.sum==right.r-right.l+) now.rss1=max(now.rss1,right.sum+left.rss1);
now.max1=max(left.max1,right.max1);
if(left.rp&&right.lp) now.max1=max(now.max1,left.rss1+right.lss1);
return now;
}
void updata(int k){
tr[k].lp=tr[lc].lp;
tr[k].rp=tr[rc].rp;
tr[k].sum=tr[lc].sum+tr[rc].sum; tr[k].lss0=tr[lc].lss0;
tr[k].rss0=tr[rc].rss0;
if(!tr[rc].lp&&!tr[lc].sum) tr[k].lss0=max(tr[k].lss0,tr[lc].r-tr[lc].l++tr[rc].lss0);
if(!tr[lc].rp&&!tr[rc].sum) tr[k].rss0=max(tr[k].rss0,tr[rc].r-tr[rc].l++tr[lc].rss0);
tr[k].max0=max(tr[lc].max0,tr[rc].max0);
if(!tr[lc].rp&&!tr[rc].lp) tr[k].max0=max(tr[k].max0,tr[lc].rss0+tr[rc].lss0); tr[k].lss1=tr[lc].lss1;
tr[k].rss1=tr[rc].rss1;
if(tr[rc].lp&&tr[lc].sum==tr[lc].r-tr[lc].l+) tr[k].lss1=max(tr[k].lss1,tr[lc].sum+tr[rc].lss1);
if(tr[lc].rp&&tr[rc].sum==tr[rc].r-tr[rc].l+) tr[k].rss1=max(tr[k].rss1,tr[rc].sum+tr[lc].rss1);
tr[k].max1=max(tr[lc].max1,tr[rc].max1);
if(tr[lc].rp&&tr[rc].lp) tr[k].max1=max(tr[k].max1,tr[lc].rss1+tr[rc].lss1);
}
void pushdown(int k){
if(~tr[k].tag){
// tr[k].rev=0;
if(tr[k].tag){
tr[lc].lp=tr[lc].rp=;
tr[lc].lss1=tr[lc].rss1=tr[lc].max1=tr[lc].sum=tr[lc].r-tr[lc].l+;
tr[lc].lss0=tr[lc].rss0=tr[lc].max0=; tr[rc].lp=tr[rc].rp=;
tr[rc].lss1=tr[rc].rss1=tr[rc].max1=tr[rc].sum=tr[rc].r-tr[rc].l+;
tr[rc].lss0=tr[rc].rss0=tr[rc].max0=;
}
else{
tr[lc].lp=tr[lc].rp=;
tr[lc].lss1=tr[lc].rss1=tr[lc].max1=tr[lc].sum=;
tr[lc].lss0=tr[lc].rss0=tr[lc].max0=tr[lc].r-tr[lc].l+; tr[rc].lp=tr[rc].rp=;
tr[rc].lss1=tr[rc].rss1=tr[rc].max1=tr[rc].sum=;
tr[rc].lss0=tr[rc].rss0=tr[rc].max0=tr[rc].r-tr[rc].l+;
}
tr[lc].tag=tr[rc].tag=tr[k].tag;tr[k].tag=-;
// return ;
}
if(tr[k].rev){
tr[k].rev=;tr[lc].rev=;tr[rc].rev=; tr[lc].sum=tr[lc].r-tr[lc].l+-tr[lc].sum; tr[lc].lp^=;tr[lc].rp^=;
swap(tr[lc].max0,tr[lc].max1);
swap(tr[lc].lss0,tr[lc].lss1);
swap(tr[lc].rss0,tr[lc].rss1); tr[rc].sum=tr[rc].r-tr[rc].l+-tr[rc].sum;
tr[rc].lp^=;tr[rc].rp^=;
swap(tr[rc].max0,tr[rc].max1);
swap(tr[rc].lss0,tr[rc].lss1);
swap(tr[rc].rss0,tr[rc].rss1);
}
}
void deal(int k,int v){
if(v){
tr[k].lp=tr[k].rp=;
tr[k].sum=tr[k].max1=tr[k].lss1=tr[k].rss1=tr[k].r-tr[k].l+;
tr[k].max0=tr[k].lss0=tr[k].rss0=;
}
else{
tr[k].lp=tr[k].rp=;
tr[k].max0=tr[k].lss0=tr[k].rss0=tr[k].r-tr[k].l+;
tr[k].sum=tr[k].max1=tr[k].lss1=tr[k].rss1=;
}
}
void vpt(int k){
if(tr[k].l==tr[k].r) return ;
pushdown(k);
vpt(lc);
vpt(rc);
}
void build(int k,int l,int r){
tr[k].l=l;tr[k].r=r;tr[k].tag=-;
if(l==r){
tr[k].lp=tr[k].rp=a[l];
tr[k].sum=tr[k].max1=tr[k].lss1=tr[k].rss1=(a[l]==);
tr[k].max0=tr[k].lss0=tr[k].rss0=(a[l]==);
return ;
}
int mid=l+r>>;
build(lc,l,mid);
build(rc,mid+,r);
updata(k);
}
void cover(int k,int x,int y,int v){
int l=tr[k].l,r=tr[k].r;
if(l==x&&r==y){
vpt(k);
deal(k,v);
if(l!=r) tr[k].tag=v;
return ;
}
pushdown(k);
int mid=l+r>>;
if(y<=mid) cover(lc,x,y,v);
else if(x>mid) cover(rc,x,y,v);
else cover(lc,x,mid,v),cover(rc,mid+,y,v);
updata(k);
}
void rever(int k,int x,int y){
int l=tr[k].l,r=tr[k].r;
if(l==x&&r==y){
vpt(k);
tr[k].sum=tr[k].r-tr[k].l+-tr[k].sum;
tr[k].lp^=;tr[k].rp^=;
swap(tr[k].max0,tr[k].max1);
swap(tr[k].lss0,tr[k].lss1);
swap(tr[k].rss0,tr[k].rss1);
if(l!=r) tr[k].rev=;
return ;
}
pushdown(k);
int mid=l+r>>;
if(y<=mid) rever(lc,x,y);
else if(x>mid) rever(rc,x,y);
else rever(lc,x,mid),rever(rc,mid+,y);
updata(k);
}
int query_sum(int k,int x,int y){
int l=tr[k].l,r=tr[k].r;
if(l==x&&r==y) return tr[k].sum;
pushdown(k);
int mid=l+r>>;
if(y<=mid) return query_sum(lc,x,y);
else if(x>mid) return query_sum(rc,x,y);
else return
query_sum(lc,x,mid)+
query_sum(rc,mid+,y);
}
sgt query_max(int k,int x,int y){
int l=tr[k].l,r=tr[k].r;
if(l==x&&r==y) return tr[k];
pushdown(k);
int mid=l+r>>;
if(y<=mid) return query_max(lc,x,y);
else if(x>mid) return query_max(rc,x,y);
else{
sgt k1=query_max(lc,x,mid);
sgt k2=query_max(rc,mid+,y);
return merge(k1,k2);
}
}
int main(){
freopen("operation.in","r",stdin);
freopen("operation.out","w",stdout);
n=read();m=read();
for(int i=;i<=n;i++) a[i]=read();
build(,,n);
for(int i=,opt,x,y;i<=m;i++){
opt=read();x=read()+;y=read()+;
if(opt<) cover(,x,y,opt);
else if(opt==) rever(,x,y);
else if(opt==) printf("%d\n",query_sum(,x,y));
else{
s=query_max(,x,y);
printf("%d\n",s.max1);
}
}
return ;
}

50分sgtTLE

#include<cstdio>
#include<iostream>
using namespace std;
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int N=;
int n,m,a[N];
int sum(int l,int r){
int res=;
for(int i=l;i<=r;i++) res+=a[i];
return res;
}
int conti(int l,int r){
int res=;
for(int i=l,j=i;i<=r;){
if(a[i]){
for(j=i+;j<=r;j++){
if(!a[j]) break;
}
res=max(res,j-i);
i=j+;
}
else i++;
}
return res;
}
void out(){
for(int j=;j<n;j++) printf("%d ",a[j]);printf("\n\n\n");
}
int main(){
n=read();m=read();
for(int i=;i<n;i++) a[i]=read();
for(int i=,opt,x,y;i<m;i++){
opt=read();x=read();y=read();
if(opt==){
for(int j=x;j<=y;j++) a[j]=;
}
if(opt==){
for(int j=x;j<=y;j++) a[j]=;
}
if(opt==){
for(int j=x;j<=y;j++) a[j]^=;
}
if(opt==){
printf("%d\n",sum(x,y));
}
if(opt==){
printf("%d\n",conti(x,y));
}
}
return ;
}

90分暴力

/*
本题的难度在于标记的下放。
下面说一下我的做法:
1.覆盖标记:直接打上就好了
2.取反标记:
<1>如果有tag标记,将tag标记取反,退出.
<2>如果有rev标记,直接退出
<3>无标记,打上rev标记,退出
维护:
sum(当前区间和),lss1(区间从左端点连续1的长度),rss1(区间从右端点连续1的长度),sc1(区间连续1的长度)
lss0,rss0,sc0同理。tag(覆盖标记和取反标记整一起了)
*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=1e5+;
const int M=;
int a[N],bl[N],n,m,size;
int tag[M],lss0[M],rss0[M],sc0[M],lss1[M],rss1[M],sc1[M],sum[M];
void init(int i){
tag[i]=-;lss0[i]=rss0[i]=sc0[i]=lss1[i]=rss1[i]=sc1[i]=sum[i]=;
for(int j=(i-)*size+;j<=min(n,i*size);j++)
if(a[j]) sum[i]++;
int fl=,p=;
for(int j=(i-)*size+;j<=min(n,i*size);j++){
if(!a[j]&&!fl) lss0[i]++;
else fl=;
if(!a[j]) p++;else p=;
sc0[i]=max(sc0[i],p);
}
fl=;
for(int j=min(n,i*size);j>(i-)*size;j--){
if(!a[j]&&!fl) rss0[i]++;
else fl=;
}
fl=,p=;
for(int j=(i-)*size+;j<=min(n,i*size);j++){
if(a[j]&&!fl) lss1[i]++;
else fl=;
if(a[j]) p++;else p=;
sc1[i]=max(sc1[i],p);
}
fl=;
for(int j=min(n,i*size);j>(i-)*size;j--){
if(a[j]&&!fl) rss1[i]++;
else fl=;
}
}
void pushdown(int i){
if(tag[i]==-) return;
if(tag[i]==||tag[i]==)
for(int j=(i-)*size+;j<=i*size;j++)
a[j]=tag[i];
else
for(int j=(i-)*size+;j<=i*size;j++)
a[j]^=;
tag[i]=-;
}
void cover(int x,int y,int v){
pushdown(bl[x]);
for(int i=x;i<=min(y,bl[x]*size);i++) a[i]=v;
init(bl[x]);
for(int i=bl[x]+;i<bl[y];i++){
tag[i]=v;
if(v) lss1[i]=rss1[i]=sc1[i]=sum[i]=size,lss0[i]=rss0[i]=sc0[i]=;
else lss1[i]=rss1[i]=sc1[i]=sum[i]=,lss0[i]=rss0[i]=sc0[i]=size;
}
if(bl[x]==bl[y]) return;
pushdown(bl[y]);
for(int i=(bl[y]-)*size+;i<=y;i++) a[i]=v;
init(bl[y]);
}
void rever(int x,int y){
pushdown(bl[x]);
for(int i=x;i<=min(y,bl[x]*size);i++) a[i]^=;
init(bl[x]);
for(int i=bl[x]+;i<bl[y];i++){
if(tag[i]==-) tag[i]=;
else if(tag[i]==) tag[i]=;
else if(tag[i]==) tag[i]=;
else tag[i]=-;
swap(lss0[i],lss1[i]);swap(rss0[i],rss1[i]);
swap(sc0[i],sc1[i]);sum[i]=size-sum[i];
}
if(bl[x]==bl[y]) return;
pushdown(bl[y]);
for(int i=(bl[y]-)*size+;i<=y;i++) a[i]^=;
init(bl[y]);
}
int query_sum(int x,int y){
int ans=;
pushdown(bl[x]);
for(int i=x;i<=min(y,bl[x]*size);i++)
if(a[i]) ans++;
for(int i=bl[x]+;i<bl[y];i++) ans+=sum[i];
if(bl[x]==bl[y]) return ans;
pushdown(bl[y]);
for(int i=(bl[y]-)*size+;i<=y;i++)
if(a[i]) ans++;
return ans;
}
int query_num(int x,int y){
int ans=,l=;
pushdown(bl[x]);
for(int i=x;i<=min(y,bl[x]*size);i++){
if(a[i]) l++;else l=;
ans=max(ans,l);
}
for(int i=bl[x]+;i<bl[y];i++){
l+=lss1[i];
ans=max(ans,l);
ans=max(ans,sc1[i]);
if(lss1[i]!=size) l=rss1[i];
}
if(bl[x]==bl[y]) return max(ans,l);
pushdown(bl[y]);
for(int i=(bl[y]-)*size+;i<=y;i++){
if(a[i]) l++;else l=;
ans=max(ans,l);
}
return ans;
}
int main(){
memset(tag,-,sizeof(tag));
scanf("%d%d",&n,&m);
size=sqrt(n);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
bl[i]=(i-)/size+;
}
for(int i=;i<=bl[n];i++) init(i);
for(int i=,op,x,y;i<=m;i++){
scanf("%d%d%d",&op,&x,&y);x++;y++;
if(op==) cover(x,y,);
if(op==) cover(x,y,);
if(op==) rever(x,y);
if(op==) printf("%d\n",query_sum(x,y));
if(op==) printf("%d\n",query_num(x,y));
}
return ;
}

[SCOI2010]序列操作[分块or线段树]的更多相关文章

  1. [BZOJ1858] [SCOI2010] 序列操作 解题报告 (线段树)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1858 Description lxhgww最近收到了一个01序列,序列里面包含了n个数, ...

  2. 【序列操作III】线段树

    题目描述 给出序列 a1,a2,…an(0≤ai≤109),有关序列的四种操作: 1. al,al+1,…,ar(1≤l≤r≤n)加上 x(-103≤x≤103) 2. al,al+1,…,ar(1≤ ...

  3. 【序列操作I】线段树

    题目描述 Lxhgww 最近收到了一个 01 序列,序列里面包含了 n(1≤n≤105)个数,这些书要么是 0,要么是 1,现在对这个序列有五种变换操作和询问操作:1. 0 a b ,把[a,b]区间 ...

  4. 洛谷P4247 序列操作 [清华集训] 线段树

    正解:线段树 解题报告: 传送门! 通过这题我get了一个神奇的,叫,线段树五问的东西hhhh 听起来有点中二但感觉真正做题的时候还是比较有用的,,,?感觉会让条理清晰很多呢,所以放一下QwQ →每个 ...

  5. BZOJ 1858: [Scoi2010]序列操作( 线段树 )

    略恶心的线段树...不过只要弄清楚了AC应该不难.... ---------------------------------------------------------------- #inclu ...

  6. BZOJ_1858_[Scoi2010]序列操作_线段树

    BZOJ_1858_[Scoi2010]序列操作_线段树 Description lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询 ...

  7. BZOJ1858 [Scoi2010]序列操作(线段树)

    题目链接 [Scoi2010]序列操作 考验代码能力的一道好题. 思想还是很简单的(直接上线段树),但是比较难写. #include <bits/stdc++.h> using names ...

  8. bzoj1858[Scoi2010]序列操作 线段树

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 3079  Solved: 1475[Submit][Statu ...

  9. 【分块】bzoj1858 [Scoi2010]序列操作

    分块 Or 线段树 分块的登峰造极之题 每块维护8个值: 包括左端点在内的最长1段: 包括右端点在内的最长1段: 该块内的最长1段: 该块内1的个数: 包括左端点在内的最长0段://这四个是因为可能有 ...

随机推荐

  1. map 类简介和例程

    一.标准库的map类型 使用map得包含map类所在的头文件 template < class Key, class Type, class Traits = less<Key>, ...

  2. linux 下安装 jdk tomcat 并配置

    linux下安装TOMCAT与JDK 第1步:新建boss用户,username:boss,password:boss 第2步:将安装用户路径设置成/app/boss [root@localhost] ...

  3. C++ 资源管理之 RAII

    RAII,它是“Resource Acquisition Is Initialization”的首字母缩写.也称为“资源获取就是初始化”,是c++等编程语言常用的管理资源.避免内存泄露的方法.它保证在 ...

  4. js ~取非运算符的妙用,将-1转为0(或假值)

    典型的运用场景就是indexOf

  5. [Jobdu] 题目1455:珍惜现在,感恩生活

    题目描述: 为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买.请问:你用有限的资金最 ...

  6. 每日英语:Dishing the Dirt on Hand-Washing Guidelines

    Americans aren't washing their hands nearly as often and as thoroughly as they should, according to ...

  7. Shape Control for .NET

    Shape Control for .NET Yang Kok Wah, 23 Mar 2017 CPOL    4.83 (155 votes)   Rate this: vote 1vote 2v ...

  8. IBM MQ 2035 或 2013认证错误的解决方法

    第一种方法: ALTER CHL(SYSTEM.BKR.CONFIG) CHLTYPE(SVRCONN) ALTER CHL(SYSTEM.ADMIN.SVRCONN) CHLTYPE(SVRCONN ...

  9. XmlFactoryBean和DefaultListableBeanFactory学习

    首先提供了一个Spring容器最简单的例子. bean的定义,MyTestBean.java public class MyTestBean { private String testStr = &q ...

  10. [ADC]Linux ADC驱动

    ADC TI adc user guide: http://processors.wiki.ti.com/index.php/Linux_Core_ADC_Users_Guide 问题: 在tools ...