题面下不出来 如果有想做的VJ查“UVA 11402 ”吧。
给出题意:对一个01区间进行4种操作。1:区间值都置为1. 2:区间值都置为0. 3:区间值01互换。4求出区间和。
题解:
第一个操作可以等效成区间值*0+1.
第二个操作可以等效成区间值*0.
第三个操作可以等效成区间值(+1)&1。
第四个操作就是线段树基本操作。
此时这题转化成了上次blog写的内题类型。但是注意,由于第三个操作没有后效行,在下传标记时注意,如果传下来的是add,此时sum等区间长度-sum(01互换,区间和是互补的)。
代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int mul[5024005],add[5024005],sum[5024005],s[1024005];
char str[1024005];
int t,q,qq,x,y,i,cnt,tt,n,m;
char opt;
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int rt,int m)
{
if(mul[rt]!=1||add[rt]!=0)
{
mul[rt<<1]=mul[rt<<1]*mul[rt];
mul[rt<<1|1]=mul[rt<<1|1]*mul[rt];
add[rt<<1]=(add[rt<<1]*mul[rt]+add[rt])&1;
add[rt<<1|1]=(add[rt<<1|1]*mul[rt]+add[rt])&1;
sum[rt<<1]=sum[rt<<1]*mul[rt];
sum[rt<<1|1]=sum[rt<<1|1]*mul[rt];
if(add[rt])
{
sum[rt<<1]=m-(m>>1)-sum[rt<<1];
sum[rt<<1|1]=(m>>1)-sum[rt<<1|1];
}
mul[rt]=1;
add[rt]=0;
}
}
void build(int l,int r,int rt)
{
sum[rt]=0;
mul[rt]=1;
if(l==r)
{
sum[rt]=s[++cnt];
return;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
}
void ch(int L,int R,int l,int r,int rt,int c)
{
if(L<=l&&r<=R)
{
mul[rt]=(mul[rt]*c);
add[rt]=(add[rt]*c);
sum[rt]=(sum[rt]*c);
return;
}
pushdown(rt,r-l+1);
int mid=(r+l)>>1;
if(L<=mid)
{
ch(L,R,l,mid,rt<<1,c);
}
if(R>mid)
ch(L,R,mid+1,r,rt<<1|1,c);
pushup(rt);
}
void ji(int L,int R,int l,int r,int rt,int c)
{
if(L<=l&&r<=R)
{
add[rt]=(add[rt]+c)&1;
sum[rt]=(r-l+1-sum[rt]);
return ;
}
pushdown(rt,r-l+1);
int mid=(r+l)>>1;
if(L<=mid)
ji(L,R,l,mid,rt<<1,c);
if(R>mid)
ji(L,R,mid+1,r,rt<<1|1,c);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return sum[rt];
pushdown(rt,r-l+1);
int mid=(l+r)>>1;
int ans=0;
if(L<=mid)
ans=ans+query(L,R,l,mid,rt<<1);
if(R>mid)
ans=ans+query(L,R,mid+1,r,rt<<1|1);
pushup(rt);
return ans;
}
int main()
{
scanf("%d",&t);
for(tt=1; tt<=t; tt++)
{
printf("Case %d:\n",tt);
memset(sum,0,sizeof(sum));
memset(add,0,sizeof(add));
memset(mul,0,sizeof(mul));
qq=0;
scanf("%d",&n);
cnt=0;
while(n--){
scanf("%d",&m);
scanf("%s",str);
int len=strlen(str);
while(m--){for( i=0; i<len; i++)s[++cnt]=str[i]-'0';}}
n=cnt;
cnt=0;
build(1,n,1);
scanf("%d",&q);
while(q--)
{
scanf("%c",&opt);
while((opt!='F')&&(opt!='E')&&(opt!='I')&&(opt!='S'))scanf("%c",&opt);
scanf("%d%d",&x,&y);
x++;
y++;
if(opt=='F')
{
ch(x,y,1,n,1,0);
ji(x,y,1,n,1,1);
}
if(opt=='E')
ch(x,y,1,n,1,0);
if(opt=='I')
ji(x,y,1,n,1,1);
if(opt=='S')
printf("Q%d: %d\n",++qq,query(x,y,1,n,1));
}
}
return 0;
}