Sequence operation
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4603 Accepted Submission(s): 1338
Problem Description
lxhgww got a sequence contains n characters which are all '0's or '1's.
We have five operations here:
Change operations:
0 a b change all characters into '0's in [a , b]
1 a b change all characters into '1's in [a , b]
2 a b change all '0's into '1's and change all '1's into '0's in [a, b]
Output operations:
3 a b output the number of '1's in [a, b]
4 a b output the length of the longest continuous '1' string in [a , b]
Input
T(T<=10) in the first line is the case number.
Each case has two integers in the first line: n and m (1 <= n , m <= 100000).
The next line contains n characters, '0' or '1' separated by spaces.
Then m lines are the operations:
op a b: 0 <= op <= 4 , 0 <= a <= b < n.
Output
For each output operation , output the result.
Sample Input
1 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
Author
lxhgww&&shǎ崽
Source
HDOJ Monthly Contest – 2010.05.01
Recommend
lcy
很好的一道题,考你有没有理解懒惰标记的本质~~
ps:这是我写的最长的代码了吧~~~
#include
#include
#include
#define lson pos<<1
#define rson pos<<1|1
using namespace std;
const int MAXN=100005;
int num[MAXN];
struct node
{
int l,r;
int msum1,msum0; //连续最长1和0
int lsum1,lsum0; //左起最长
int rsum1,rsum0; //右起最长
int lazy; //标记
int sum; //最长1
int mid()
{
return (l+r)>>1;
}
};
node tree[MAXN*4];
inline void pushup(int pos)
{
tree[pos].msum0=max(tree[lson].msum0,tree[rson].msum0);
tree[pos].msum1=max(tree[lson].msum1,tree[rson].msum1);
tree[pos].lsum0=tree[lson].lsum0;
tree[pos].lsum1=tree[lson].lsum1;
tree[pos].rsum0=tree[rson].rsum0;
tree[pos].rsum1=tree[rson].rsum1;
tree[pos].msum0=max(tree[pos].msum0,tree[lson].rsum0+tree[rson].lsum0);
tree[pos].msum1=max(tree[pos].msum1,tree[lson].rsum1+tree[rson].lsum1);
int l1=tree[lson].r-tree[lson].l+1;
int l2=tree[rson].r-tree[rson].l+1;
if(l1==tree[lson].lsum0)
tree[pos].lsum0+=tree[rson].lsum0;
if(l1==tree[lson].lsum1)
tree[pos].lsum1+=tree[rson].lsum1;
if(l2==tree[rson].rsum0)
tree[pos].rsum0+=tree[lson].rsum0;
if(l2==tree[rson].rsum1)
tree[pos].rsum1+=tree[lson].rsum1;
tree[pos].sum=tree[lson].sum+tree[rson].sum;
}
inline void pushdown(int pos)
{
int x=tree[pos].lazy;
if(x==0)
{
tree[lson].lazy=0;
tree[lson].sum=0;
tree[lson].lsum1=tree[lson].rsum1=tree[lson].msum1=0;
tree[lson].lsum0=tree[lson].rsum0=tree[lson].msum0=tree[lson].r-tree[lson].l+1;
tree[rson].lazy=0;
tree[rson].sum=0;
tree[rson].lsum1=tree[rson].rsum1=tree[rson].msum1=0;
tree[rson].lsum0=tree[rson].rsum0=tree[rson].msum0=tree[rson].r-tree[rson].l+1;
}
else if(x==1)
{
tree[lson].lazy=1;
tree[lson].sum=tree[lson].r-tree[lson].l+1;
tree[lson].lsum1=tree[lson].rsum1=tree[lson].msum1=tree[lson].r-tree[lson].l+1;
tree[lson].lsum0=tree[lson].rsum0=tree[lson].msum0=0;
tree[rson].lazy=1;
tree[rson].sum=tree[rson].r-tree[rson].l+1;
tree[rson].lsum1=tree[rson].rsum1=tree[rson].msum1=tree[rson].r-tree[rson].l+1;
tree[rson].lsum0=tree[rson].rsum0=tree[rson].msum0=0;
}
else if(x==2)
{
if(tree[lson].l!=tree[lson].r)
pushdown(lson);
tree[lson].lazy=2;
tree[lson].sum=tree[lson].r-tree[lson].l+1-tree[lson].sum;
int t=tree[lson].lsum1;
tree[lson].lsum1=tree[lson].lsum0;
tree[lson].lsum0=t;
t=tree[lson].rsum1;
tree[lson].rsum1=tree[lson].rsum0;
tree[lson].rsum0=t;
t=tree[lson].msum1;
tree[lson].msum1=tree[lson].msum0;
tree[lson].msum0=t;
if(tree[rson].l!=tree[rson].r)
pushdown(rson);
tree[rson].lazy=2;
tree[rson].sum=tree[rson].r-tree[rson].l+1-tree[rson].sum;
t=tree[rson].lsum1;
tree[rson].lsum1=tree[rson].lsum0;
tree[rson].lsum0=t;
t=tree[rson].rsum1;
tree[rson].rsum1=tree[rson].rsum0;
tree[rson].rsum0=t;
t=tree[rson].msum1;
tree[rson].msum1=tree[rson].msum0;
tree[rson].msum0=t;
}
tree[pos].lazy=-1;
}
void build(int l,int r,int pos)
{
tree[pos].l=l;
tree[pos].r=r;
if(l==r)
{
int x;
scanf("%d",&x);
tree[pos].lazy=-1;
tree[pos].msum0=!x;
tree[pos].msum1=x;
tree[pos].lsum0=!x;
tree[pos].lsum1=x;
tree[pos].rsum0=!x;
tree[pos].rsum1=x;
tree[pos].sum=x;
return ;
}
int mid=tree[pos].mid();
build(l,mid,lson);
build(mid+1,r,rson);
tree[pos].lazy=-1;
pushup(pos);
}
void update(int l,int r,int x,int pos)
{
if(l==tree[pos].l&&r==tree[pos].r)
{
if(x==0)
{
tree[pos].lazy=0;
tree[pos].sum=0;
tree[pos].lsum1=tree[pos].rsum1=tree[pos].msum1=0;
tree[pos].lsum0=tree[pos].rsum0=tree[pos].msum0=tree[pos].r-tree[pos].l+1;
}
else if(x==1)
{
tree[pos].lazy=1;
tree[pos].sum=tree[pos].r-tree[pos].l+1;
tree[pos].lsum1=tree[pos].rsum1=tree[pos].msum1=tree[pos].r-tree[pos].l+1;
tree[pos].lsum0=tree[pos].rsum0=tree[pos].msum0=0;
}
else
{
if(l!=r) //是1,或0的时候可以直接覆盖,但如果是2的话必须向下更新,,本质~因为下面的状态随上面的变化,
pushdown(pos);
tree[pos].lazy=2;
tree[pos].sum=tree[pos].r-tree[pos].l+1-tree[pos].sum;
int t=tree[pos].lsum1;
tree[pos].lsum1=tree[pos].lsum0;
tree[pos].lsum0=t;
t=tree[pos].rsum1;
tree[pos].rsum1=tree[pos].rsum0;
tree[pos].rsum0=t;
t=tree[pos].msum1;
tree[pos].msum1=tree[pos].msum0;
tree[pos].msum0=t;
}
return ;
}
pushdown(pos);
int mid=tree[pos].mid();
if(r<=mid)
update(l,r,x,lson);
else if(l>mid)
update(l,r,x,rson);
else
{
update(l,mid,x,lson);
update(mid+1,r,x,rson);
}
pushup(pos);
}
int queryR(int l,int r,int pos)
{
if(r-l+1>=tree[pos].rsum1)
return tree[pos].rsum1;
else
return r-l+1;
}
int queryL(int l,int r,int pos)
{
if(r-l+1>=tree[pos].lsum1)
return tree[pos].lsum1;
else
return r-l+1;
}
int query(int l,int r,int x,int pos)
{
if(l==tree[pos].l&&r==tree[pos].r)
{
if(x==3)
return tree[pos].sum;
else
return tree[pos].msum1;
}
pushdown(pos);
int mid=tree[pos].mid();
if(x==3)
{
if(r<=mid)
return query(l,r,x,lson);
else if(l>mid)
return query(l,r,x,rson);
else
return query(l,mid,x,lson)+query(mid+1,r,x,rson);
}
else
{
if(r<=mid)
return query(l,r,x,lson);
else if(l>mid)
return query(l,r,x,rson);
else
{
int res=query(l,mid,x,lson);
res=max(res,query(mid+1,r,x,rson));
res=max(res,queryR(l,mid,lson)+queryL(mid+1,r,rson));
return res;
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
build(1,n,1);
int i;
for(i=0;i