您的位置:首页 > 其它

[SCOI2010]序列操作[分块or线段树]

2017-03-30 18:06 302 查看
[b]

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


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+5;
const int M=505;
int a
,bl
,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]=-1;lss0[i]=rss0[i]=sc0[i]=lss1[i]=rss1[i]=sc1[i]=sum[i]=0;
for(int j=(i-1)*size+1;j<=min(n,i*size);j++)
if(a[j]) sum[i]++;
int fl=0,p=0;
for(int j=(i-1)*size+1;j<=min(n,i*size);j++){
if(!a[j]&&!fl) lss0[i]++;
else fl=1;
if(!a[j]) p++;else p=0;
sc0[i]=max(sc0[i],p);
}
fl=0;
for(int j=min(n,i*size);j>(i-1)*size;j--){
if(!a[j]&&!fl) rss0[i]++;
else fl=1;
}
fl=0,p=0;
for(int j=(i-1)*size+1;j<=min(n,i*size);j++){
if(a[j]&&!fl) lss1[i]++;
else fl=1;
if(a[j]) p++;else p=0;
sc1[i]=max(sc1[i],p);
}
fl=0;
for(int j=min(n,i*size);j>(i-1)*size;j--){
if(a[j]&&!fl) rss1[i]++;
else fl=1;
}
}
void pushdown(int i){
if(tag[i]==-1) return;
if(tag[i]==0||tag[i]==1)
for(int j=(i-1)*size+1;j<=i*size;j++)
a[j]=tag[i];
else
for(int j=(i-1)*size+1;j<=i*size;j++)
a[j]^=1;
tag[i]=-1;
}
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]+1;i<bl[y];i++){
tag[i]=v;
if(v) lss1[i]=rss1[i]=sc1[i]=sum[i]=size,lss0[i]=rss0[i]=sc0[i]=0;
else lss1[i]=rss1[i]=sc1[i]=sum[i]=0,lss0[i]=rss0[i]=sc0[i]=size;
}
if(bl[x]==bl[y]) return;
pushdown(bl[y]);
for(int i=(bl[y]-1)*size+1;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]^=1;
init(bl[x]);
for(int i=bl[x]+1;i<bl[y];i++){
if(tag[i]==-1) tag[i]=2;
else if(tag[i]==0) tag[i]=1;
else if(tag[i]==1) tag[i]=0;
else tag[i]=-1;
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]-1)*size+1;i<=y;i++) a[i]^=1;
init(bl[y]);
}
int query_sum(int x,int y){
int ans=0;
pushdown(bl[x]);
for(int i=x;i<=min(y,bl[x]*size);i++)
if(a[i]) ans++;
for(int i=bl[x]+1;i<bl[y];i++) ans+=sum[i];
if(bl[x]==bl[y]) return ans;
pushdown(bl[y]);
for(int i=(bl[y]-1)*size+1;i<=y;i++)
if(a[i]) ans++;
return ans;
}
int query_num(int x,int y){
int ans=0,l=0;
pushdown(bl[x]);
for(int i=x;i<=min(y,bl[x]*size);i++){
if(a[i]) l++;else l=0;
ans=max(ans,l);
}
for(int i=bl[x]+1;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]-1)*size+1;i<=y;i++){
if(a[i]) l++;else l=0;
ans=max(ans,l);
}
return ans;
}
int main(){
memset(tag,-1,sizeof(tag));
scanf("%d%d",&n,&m);
size=sqrt(n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
bl[i]=(i-1)/size+1;
}
for(int i=1;i<=bl
;i++) init(i);
for(int i=1,op,x,y;i<=m;i++){
scanf("%d%d%d",&op,&x,&y);x++;y++;
if(op==0) cover(x,y,0);
if(op==1) cover(x,y,1);
if(op==2) rever(x,y);
if(op==3) printf("%d\n",query_sum(x,y));
if(op==4) printf("%d\n",query_num(x,y));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: