Sequence operation
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 9077 Accepted Submission(s): 2764
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
5
2
6
5
题意:首先给出一组数据:由0和1组成,然后有5种操作。
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的个数。
思路:就是线段树区间求和,区间更新,区间合并,区间修改,懒惰结点。思路上没什么难的,但是细节真的巨多,巨多啊。可能因为我代码功力弱的原因,调到绝望。
下面总结一下我被卡的重要细节:
1,查询区间中1的最多连续个数时要考虑三种情况,左区间最长,右区间区间最长和左区间右端连续1长度+右区间左端点连续长度进行三者比较。
2,左区间左端点连续长度在左区间全是1的情况下等于左区间长度+右区间左端点连续长度。右区间右端点连续长度同理。
3,懒惰结点下放时当前懒惰结点是区间0边1,1变0时,要考虑其左右孩子的懒惰结点被标记的是什么。
(1)如果其孩子的懒惰结点没被标记,那么直接标记下放。
(2)如果其孩子懒惰结点是全变1,那么将其变成全变0。
(3)如果其孩子懒惰结点是全变0,那么将其变成全变1。
(4)如果其孩子懒惰结点是0变1,1变0,那么将其变为未标记状态。
可以仔细考虑第三条,因为2号操作的懒惰结点的下放会影响到孩子的懒惰结点,所以要进行判断。
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <queue>
#include <time.h>
#include <vector>
#include <string>
#include <math.h>
#include <cstring>
#include <cstdlib>
#include <stdio.h>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define PI acos(-1)
#define ll long long
#define LL long long
#define inf 0x3f3f3f3f
#define ull unsigned long long
using namespace std;
const int maxn=100005;
struct node
{
int l,r;
int sum;
int add;
int len1_max;
int l1_max;
int r1_max;
int len0_max;
int l0_max;
int r0_max;
}tree[maxn*6];
void pushdown(int i)
{
if(tree[i].add==1)//全变成1
{
tree[i].add=0;
tree[i*2].add=1;
tree[i*2].sum=tree[i*2].r-tree[i*2].l+1;
tree[i*2+1].add=1;
tree[i*2+1].sum=tree[i*2+1].r-tree[i*2+1].l+1;
tree[i*2].len0_max=0;
tree[i*2].l0_max=0;
tree[i*2].r0_max=0;
tree[i*2].len1_max=tree[i*2].r-tree[i*2].l+1;
tree[i*2].l1_max=tree[i*2].r-tree[i*2].l+1;
tree[i*2].r1_max=tree[i*2].r-tree[i*2].l+1;
tree[i*2+1].len0_max=0;
tree[i*2+1].l0_max=0;
tree[i*2+1].r0_max=0;
tree[i*2+1].len1_max=tree[i*2+1].r-tree[i*2+1].l+1;
tree[i*2+1].l1_max=tree[i*2+1].r-tree[i*2+1].l+1;
tree[i*2+1].r1_max=tree[i*2+1].r-tree[i*2+1].l+1;
}
else if(tree[i].add==2)//全变成0
{
tree[i].add=0;
tree[i*2].add=2;
tree[i*2].sum=0;
tree[i*2+1].add=2;
tree[i*2+1].sum=0;
tree[i*2].len0_max=tree[i*2].r-tree[i*2].l+1;
tree[i*2].l0_max=tree[i*2].r-tree[i*2].l+1;
tree[i*2].r0_max=tree[i*2].r-tree[i*2].l+1;
tree[i*2].len1_max=0;
tree[i*2].l1_max=0;
tree[i*2].r1_max=0;
tree[i*2+1].len0_max=tree[i*2+1].r-tree[i*2+1].l+1;
tree[i*2+1].l0_max=tree[i*2+1].r-tree[i*2+1].l+1;
tree[i*2+1].r0_max=tree[i*2+1].r-tree[i*2+1].l+1;
tree[i*2+1].len1_max=0;
tree[i*2+1].l1_max=0;
tree[i*2+1].r1_max=0;
}
else if(tree[i].add==3)//将所有数取逆
{
tree[i].add=0;
//tree[i*2].add=3;
if(tree[i*2].add==1) tree[i*2].add=2;
else if(tree[i*2].add==2) tree[i*2].add=1;
else if(tree[i*2].add==3) tree[i*2].add=0;
else if(tree[i*2].add==0) tree[i*2].add=3;
tree[i*2].sum=tree[i*2].r-tree[i*2].l+1-tree[i*2].sum;
//tree[i*2+1].add=3;
if(tree[i*2+1].add==1) tree[i*2+1].add=2;
else if(tree[i*2+1].add==2) tree[i*2+1].add=1;
else if(tree[i*2+1].add==3) tree[i*2+1].add=0;
else if(tree[i*2+1].add==0) tree[i*2+1].add=3;
tree[i*2+1].sum=tree[i*2+1].r-tree[i*2+1].l+1-tree[i*2+1].sum;
swap(tree[i*2].len0_max,tree[i*2].len1_max);
swap(tree[i*2].l0_max,tree[i*2].l1_max);
swap(tree[i*2].r0_max,tree[i*2].r1_max);
swap(tree[i*2+1].len0_max,tree[i*2+1].len1_max);
swap(tree[i*2+1].l0_max,tree[i*2+1].l1_max);
swap(tree[i*2+1].r0_max,tree[i*2+1].r1_max);
}
}
void pushup(int i)
{
tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
tree[i].len1_max=max(tree[i*2].len1_max,tree[i*2+1].len1_max);
tree[i].len1_max=max(tree[i].len1_max,tree[i*2].r1_max+tree[i*2+1].l1_max);
if(tree[i*2].len1_max==tree[i*2].r-tree[i*2].l+1) tree[i].l1_max=tree[i*2].l1_max+tree[i*2+1].l1_max;
else tree[i].l1_max=tree[i*2].l1_max;
if(tree[i*2+1].len1_max==tree[i*2+1].r-tree[i*2+1].l+1) tree[i].r1_max=tree[i*2+1].r1_max+tree[i*2].r1_max;
else tree[i].r1_max=tree[i*2+1].r1_max;
tree[i].len0_max=max(tree[i*2].len0_max,tree[i*2+1].len0_max);
tree[i].len0_max=max(tree[i].len0_max,tree[i*2].r0_max+tree[i*2+1].l0_max);
if(tree[i*2].len0_max==tree[i*2].r-tree[i*2].l+1) tree[i].l0_max=tree[i*2].l0_max+tree[i*2+1].l0_max;
else tree[i].l0_max=tree[i*2].l0_max;
if(tree[i*2+1].len0_max==tree[i*2+1].r-tree[i*2+1].l+1) tree[i].r0_max=tree[i*2+1].r0_max+tree[i*2].r0_max;
else tree[i].r0_max=tree[i*2+1].r0_max;
}
void build(int i,int l,int r)
{
tree[i].l=l;
tree[i].r=r;
tree[i].add=0;
if(l==r)
{
scanf("%d",&tree[i].sum);
if(tree[i].sum==1)
{
tree[i].len0_max=0;
tree[i].l0_max=0;
tree[i].r0_max=0;
tree[i].len1_max=1;
tree[i].l1_max=1;
tree[i].r1_max=1;
}
else
{
tree[i].len0_max=1;
tree[i].l0_max=1;
tree[i].r0_max=1;
tree[i].len1_max=0;
tree[i].l1_max=0;
tree[i].r1_max=0;
}
return ;
}
int mid=(l+r)>>1;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
pushup(i);
}
void update(int L,int R,int val,int i)
{
pushdown(i);
if(L<=tree[i].l&&tree[i].r<=R)
{
if(val==1)//全变成1
{
tree[i].sum=tree[i].r-tree[i].l+1;
tree[i].add=1;
tree[i].len1_max=tree[i].r-tree[i].l+1;
tree[i].l1_max=tree[i].r-tree[i].l+1;
tree[i].r1_max=tree[i].r-tree[i].l+1;
tree[i].len0_max=0;
tree[i].l0_max=0;
tree[i].r0_max=0;
}
else if(val==2)//全变成0
{
tree[i].sum=0;
tree[i].add=2;
tree[i].len0_max=tree[i].r-tree[i].l+1;
tree[i].l0_max=tree[i].r-tree[i].l+1;
tree[i].r0_max=tree[i].r-tree[i].l+1;
tree[i].len1_max=0;
tree[i].l1_max=0;
tree[i].r1_max=0;
}
else if(val==3)//全取反
{
tree[i].sum=tree[i].r-tree[i].l+1-tree[i].sum;
tree[i].add=3;
swap(tree[i].len0_max,tree[i].len1_max);
swap(tree[i].l0_max,tree[i].l1_max);
swap(tree[i].r0_max,tree[i].r1_max);
}
return ;
}
int mid=(tree[i].l+tree[i].r)>>1;
if(mid>=L) update(L,R,val,i*2);
if(mid<R) update(L,R,val,i*2+1);
pushup(i);
}
int query(int L,int R,int i)
{
pushdown(i);
if(L<=tree[i].l&&tree[i].r<=R)
{
return tree[i].sum;
}
int mid=(tree[i].l+tree[i].r)>>1;
int ans=0;
if(L<=mid) ans+=query(L,R,i*2);
if(mid<R) ans+=query(L,R,i*2+1);
return ans;
}
int query_len(int L,int R,int i)
{
pushdown(i);
if(L<=tree[i].l&&tree[i].r<=R)
{
return tree[i].len1_max;
}
int mid=(tree[i].l+tree[i].r)>>1;
int ans=0;
if(R <= mid)return query_len(L,R,i*2);
else if(L > mid)return query_len(L,R,i*2+1);
else
{
int ans1 = 0,ans2 = 0;
ans1 = query_len(L,mid,i*2);
ans2 = query_len(mid+1,R,i*2+1);
ans = min(tree[i<<1].r1_max,mid-L+1)+min(tree[i<<1|1].l1_max,R-mid);
return max(ans,max(ans1,ans2));
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,q,op,a,b;
scanf("%d%d",&n,&q);
memset(tree,0,sizeof(tree));
build(1,1,n);
while(q--)
{
scanf("%d%d%d",&op,&a,&b);
a++;
b++;
if(op==0)//全变成0
{
update(a,b,2,1);
}
else if(op==1)//全变成1
{
update(a,b,1,1);
}
else if(op==2)//0变1,1变0
{
update(a,b,3,1);
}
else if(op==3)//区间求和
{
cout<<query(a,b,1)<<endl;
}
else if(op==4)//区间最长连续1
{
cout<<query_len(a,b,1)<<endl;
}
}
}
}