1858: [Scoi2010]序列操作
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2171 Solved: 1087
[ Submit][ Status][ Discuss]
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;">
[
Submit][
Status][
Discuss]
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
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
2
6
5
HINT
对于30%的数据,1<=n, m<=1000
对于100%的数据,1<=n, m<=100000
Source
题解:线段树
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 500003
using namespace std;
int delta[N],rev[N],tr[N],ls[N],rs[N],a[N],b[N],tr1[N],ls1[N],rs1[N];
int num[N],n,m;
struct data
{
int tr,ls,rs;
int l,r;
};
void update(int x,int l,int r)
{
int mid=(l+r)/2;
a[x]=a[x<<1]+a[x<<1|1];
b[x]=b[x<<1]+b[x<<1|1];
tr[x]=max(tr[x<<1],max(tr[x<<1|1],rs[x<<1]+ls[x<<1|1]));
tr1[x]=max(tr1[x<<1],max(tr1[x<<1|1],rs1[x<<1]+ls1[x<<1|1]));
ls[x]=ls[x<<1]+(ls[x<<1]==mid-l+1?ls[x<<1|1]:0);
rs[x]=rs[x<<1|1]+(rs[x<<1|1]==r-mid?rs[x<<1]:0);
ls1[x]=ls1[x<<1]+(ls1[x<<1]==mid-l+1?ls1[x<<1|1]:0);
rs1[x]=rs1[x<<1|1]+(rs1[x<<1|1]==r-mid?rs1[x<<1]:0);
}
void solve(int now,int l,int r,int v)
{
if (v==2) tr1[now]=ls1[now]=rs1[now]=b[now]=0,rev[now]=0,delta[now]=v,
tr[now]=ls[now]=rs[now]=a[now]=(r-l+1);
else
tr[now]=ls[now]=rs[now]=a[now]=0,rev[now]=0,delta[now]=v,
tr1[now]=ls1[now]=rs1[now]=b[now]=(r-l+1);
}
void solve1(int now)
{
if (delta[now]&&rev[now])
rev[now]=0,delta[now]=(delta[now]==1?2:1);
swap(tr[now],tr1[now]);
swap(a[now],b[now]);
swap(ls[now],ls1[now]);
swap(rs[now],rs1[now]);
}
void pushdown(int x,int l,int r)
{
int mid=(l+r)/2;
if (delta[x])
{
delta[x<<1]=delta[x]; delta[x<<1|1]=delta[x];
solve(x<<1,l,mid,delta[x]); solve(x<<1|1,mid+1,r,delta[x]);
delta[x]=0; rev[x]=0;
}
if (rev[x])
{
rev[x<<1]^=1; rev[x<<1|1]^=1;
solve1(x<<1); solve1(x<<1|1);
rev[x]=0;
}
}
void build(int now,int l,int r)
{
if (l==r)
{
if(num[l]) tr[now]=ls[now]=rs[now]=a[now]=1;
else tr1[now]=ls1[now]=rs1[now]=b[now]=1;
return;
}
int mid=(l+r)/2;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
update(now,l,r);
}
void qjchange(int now,int l,int r,int ll,int rr,int v)
{
if (ll<=l&&r<=rr)
{
if (v==2) tr1[now]=ls1[now]=rs1[now]=b[now]=0,rev[now]=0,delta[now]=v,
tr[now]=ls[now]=rs[now]=a[now]=(r-l+1);
else
tr[now]=ls[now]=rs[now]=a[now]=0,rev[now]=0,delta[now]=v,
tr1[now]=ls1[now]=rs1[now]=b[now]=(r-l+1);
return;
}
int mid=(l+r)/2;
pushdown(now,l,r);
if (ll<=mid) qjchange(now<<1,l,mid,ll,rr,v);
if (rr>mid) qjchange(now<<1|1,mid+1,r,ll,rr,v);
update(now,l,r);
}
void qjrev(int now,int l,int r,int ll,int rr)
{
if (ll<=l&&r<=rr)
{
rev[now]^=1;
if (delta[now]&&rev[now])
{
rev[now]=0,delta[now]=(delta[now]==1?2:1);
if (delta[now]==2) tr1[now]=ls1[now]=rs1[now]=b[now]=0,rev[now]=0,
tr[now]=ls[now]=rs[now]=a[now]=(r-l+1);
else
tr[now]=ls[now]=rs[now]=a[now]=0,rev[now]=0,
tr1[now]=ls1[now]=rs1[now]=b[now]=(r-l+1);
}
else
{
swap(tr[now],tr1[now]);
swap(a[now],b[now]);
swap(ls[now],ls1[now]);
swap(rs[now],rs1[now]);
}
return;
}
int mid=(l+r)/2;
pushdown(now,l,r);
if (ll<=mid) qjrev(now<<1,l,mid,ll,rr);
if (rr>mid) qjrev(now<<1|1,mid+1,r,ll,rr);
update(now,l,r);
}
int qjsum(int now,int l,int r,int ll,int rr)
{
if (ll<=l&&r<=rr) return a[now];
int mid=(l+r)/2;
pushdown(now,l,r);
int ans=0;
if (ll<=mid) ans+=qjsum(now<<1,l,mid,ll,rr);
if (rr>mid) ans+=qjsum(now<<1|1,mid+1,r,ll,rr);
return ans;
}
void clear (data &a)
{
a.tr=a.ls=a.rs=0;
}
data calc(data a,data b)
{
data c;
c.l=min(a.l,b.l); c.r=max(a.r,b.r);
c.tr=max(a.tr,max(b.tr,a.rs+b.ls));
c.ls=a.ls+(a.ls==a.r-a.l+1?b.ls:0);
c.rs=b.rs+(b.rs==b.r-b.l+1?a.rs:0);
return c;
}
data merge(int now,int l,int r,int ll,int rr)
{
if (ll<=l&&r<=rr)
{
data a; clear(a); a.l=l; a.r=r;
a.tr=tr[now]; a.ls=ls[now]; a.rs=rs[now];
return a;
}
int mid=(l+r)/2;
pushdown(now,l,r);
data a; clear(a); a.l=max(ll,l); a.r=0;
bool f=false;
if (ll<=mid) {
a=merge(now<<1,l,mid,ll,rr);
f=true;
}
if (rr>mid) {
data b; clear(b);
b=merge(now<<1|1,mid+1,r,ll,rr);
if (f) a=calc(a,b);
else a=b;
}
return a;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&num[i]);
build(1,1,n);
for (int i=1;i<=m;i++)
{
int k,x,y; scanf("%d%d%d",&k,&x,&y); x++; y++;
if (k<=1)
qjchange(1,1,n,x,y,k+1);
if (k==2) qjrev(1,1,n,x,y);
if (k==3) printf("%d\n",qjsum(1,1,n,x,y));
if (k==4)
{
data a=merge(1,1,n,x,y);
printf("%d\n",a.tr);
}
}
}