您的位置:首页 > 其它

[BZOJ 1858][Scoi2010]序列操作(线段树)

2017-03-03 20:34 295 查看

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

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

Sample Output

5

2

6

5

HINT

对于30%的数据,1<=n, m<=1000

对于100%的数据,1<=n, m<=100000

Solution

啊为什么调了那么长时间…

后来发现是push_down操作给子节点标lazy的时候忘记把它们的rev标记去掉了 泪

线段记录区间里1和0的个数、最长连续的1和0的个数、左端连续的1和0的个数、右端连续的1和0的个数,然后记录一个lazy标记和rev标记(取反)。

取反操作的时候遇到lazy标记可以直接对lazy取反,标记lazy的时候要记得把rev去掉

那个最长连续1的询问函数直接返回了一个结构体,合并操作和线段树的更新差不多,具体实现看代码

感觉我没有办法写出优美的代码,不知道为什么代码长度这么长= =

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<assert.h>
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define mid(a,b) ((a+b)>>1)
#define MAXN 100005
using namespace std;
int n,m;
int x[MAXN],ans;
struct Node{
int l,r,siz;
int num1,lnum1,rnum1,maxnum1;
int num0,lnum0,rnum0,maxnum0;
int lazy,rev;
}t[MAXN*4];
Node operator + (const Node& a,const Node& b)
{
Node ans;

ans.lnum0=a.lnum0;
if(a.lnum0==a.siz)
ans.lnum0=a.siz+b.lnum0;
ans.lnum1=a.lnum1;
if(a.lnum1==a.siz)
ans.lnum1=a.siz+b.lnum1;

ans.rnum0=b.rnum0;
if(b.rnum0==b.siz)
ans.rnum0=b.siz+a.rnum0;
ans.rnum1=b.rnum1;
if(b.rnum1==b.siz)
ans.rnum1=b.siz+a.rnum1;

ans.num0=a.num0+b.num0;
ans.num1=a.num1+b.num1;

ans.maxnum0=Max(a.maxnum0,b.maxnum0);
ans.maxnum0=Max(ans.maxnum0,a.rnum0+b.lnum0);

ans.maxnum1=Max(a.maxnum1,b.maxnum1);
ans.maxnum1=Max(ans.maxnum1,a.rnum1+b.lnum1);
return ans;
}
void _exchange(int idx)
{
swap(t[idx].lnum0,t[idx].lnum1);
swap(t[idx].rnum0,t[idx].rnum1);
swap(t[idx].num0,t[idx].num1);
swap(t[idx].maxnum0,t[idx].maxnum1);
}
void push_down(int idx)
{
if(t[idx].l==t[idx].r)return;
if(t[idx].lazy!=-1)
{
int f=t[idx].lazy;
t[idx*2].lazy=t[idx*2+1].lazy=t[idx].lazy;
t[idx*2].rev=t[idx*2+1].rev=0;
t[idx].lazy=-1;
t[idx*2].lnum0=t[idx*2].rnum0=t[idx*2].num0=t[idx*2].maxnum0=(f==0)*t[idx*2].siz;
t[idx*2].lnum1=t[idx*2].rnum1=t[idx*2].num1=t[idx*2].maxnum1=(f==1)*t[idx*2].siz;
t[idx*2+1].lnum0=t[idx*2+1].rnum0=t[idx*2+1].num0=t[idx*2+1].maxnum0=(f==0)*t[idx*2+1].siz;
t[idx*2+1].lnum1=t[idx*2+1].rnum1=t[idx*2+1].num1=t[idx*2+1].maxnum1=(f==1)*t[idx*2+1].siz;
}
if(t[idx].rev)
{
t[idx].rev=0;
t[idx*2].rev^=1;
t[idx*2+1].rev^=1;
_exchange(idx*2);
_exchange(idx*2+1);
}
}
void _update(int idx)
{
t[idx].lnum0=t[idx*2].lnum0;
if(t[idx*2].lnum0==t[idx*2].siz)
t[idx].lnum0=t[idx*2].siz+t[idx*2+1].lnum0;
t[idx].lnum1=t[idx*2].lnum1;
if(t[idx*2].lnum1==t[idx*2].siz)
t[idx].lnum1=t[idx*2].siz+t[idx*2+1].lnum1;

t[idx].rnum0=t[idx*2+1].rnum0;
if(t[idx*2+1].rnum0==t[idx*2+1].siz)
t[idx].rnum0=t[idx*2+1].siz+t[idx*2].rnum0;
t[idx].rnum1=t[idx*2+1].rnum1;
if(t[idx*2+1].rnum1==t[idx*2+1].siz)
t[idx].rnum1=t[idx*2+1].siz+t[idx*2].rnum1;

t[idx].num0=t[idx*2].num0+t[idx*2+1].num0;
t[idx].num1=t[idx*2].num1+t[idx*2+1].num1;

t[idx].maxnum0=Max(t[idx*2].maxnum0,t[idx*2+1].maxnum0);
t[idx].maxnum0=Max(t[idx].maxnum0,t[idx*2].rnum0+t[idx*2+1].lnum0);

t[idx].maxnum1=Max(t[idx*2].maxnum1,t[idx*2+1].maxnum1);
t[idx].maxnum1=Max(t[idx].maxnum1,t[idx*2].rnum1+t[idx*2+1].lnum1);
}
void _build(int idx,int a,int b)
{
t[idx].siz=b-a+1;
t[idx].l=a;t[idx].r=b;
t[idx].lazy=-1;
t[idx].rev=0;
if(a==b)
{
if(x[a])
{
t[idx].lnum0=t[idx].rnum0=t[idx].num0=t[idx].maxnum0=0;
t[idx].lnum1=t[idx].rnum1=t[idx].num1=t[idx].maxnum1=1;
}
else
{
t[idx].lnum0=t[idx].rnum0=t[idx].num0=t[idx].maxnum0=1;
t[idx].lnum1=t[idx].rnum1=t[idx].num1=t[idx].maxnum1=0;
}
return;
}
int m=mid(a,b);
_build(idx*2,a,m);
_build(idx*2+1,m+1,b);
_update(idx);
}
void _turn(int idx,int a,int b,int f)
{
push_down(idx);
if(t[idx].l==t[idx].r)
{
t[idx].lnum0=t[idx].rnum0=t[idx].num0=t[idx].maxnum0=(f==0);
t[idx].lnum1=t[idx].rnum1=t[idx].num1=t[idx].maxnum1=(f==1);
return;
}
if(a<=t[idx].l&&b>=t[idx].r)
{
t[idx].lnum0=t[idx].rnum0=t[idx].num0=t[idx].maxnum0=(f==0)*t[idx].siz;
t[idx].lnum1=t[idx].rnum1=t[idx].num1=t[idx].maxnum1=(f==1)*t[idx].siz;
if(t[idx].rev)
t[idx].rev=0;
t[idx].lazy=f;
return;
}

int m=mid(t[idx].l,t[idx].r);
if(b<=m)_turn(idx*2,a,b,f);
else if(a>m)_turn(idx*2+1,a,b,f);
else
{
_turn(idx*2,a,b,f);
_turn(idx*2+1,a,b,f);
}
_update(idx);
}
void _reverse(int idx,int a,int b)
{
push_down(idx);
if(t[idx].l==t[idx].r)
{
_exchange(idx);
return;
}
if(a<=t[idx].l&&b>=t[idx].r)
{
if(t[idx].lazy!=-1)
{
t[idx].lazy^=1;
_exchange(idx);
return;
}
t[idx].rev^=1;
_exchange(idx);
return;
}
int m=mid(t[idx].l,t[idx].r);
if(b<=m)_reverse(idx*2,a,b);
else if(a>m)_reverse(idx*2+1,a,b);
else
{
_reverse(idx*2,a,b);
_reverse(idx*2+1,a,b);
}
_update(idx);
}
void _count(int idx,int a,int b)
{
push_down(idx);
if(t[idx].l==t[idx].r)
{
ans+=t[idx].num1;
return;
}

if(a<=t[idx].l&&b>=t[idx].r)
{
ans+=t[idx].num1;
return;
}

int m=mid(t[idx].l,t[idx].r);
if(b<=m)_count(idx*2,a,b);
else if(a>m)_count(idx*2+1,a,b);
else
{
_count(idx*2,a,b);
_count(idx*2+1,a,b);
}
}
Node _query(int idx,int a,int b)
{
push_down(idx);
if(a==t[idx].l&&b==t[idx].r)
{
return t[idx];
}

int m=mid(t[idx].l,t[idx].r);
if(a<=m&&b>m)
{
return _query(idx*2,a,m)+_query(idx*2+1,m+1,b);
}
if(a>m)
{
return _query(idx*2+1,a,b);
}
if(b<=m)
{
return _query(idx*2,a,b);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",&x[i]);
_build(1,0,n-1);
for(int i=1;i<=m;i++)
{
int opt,a,b;
scanf("%d%d%d",&opt,&a,&b);
switch(opt)
{
case 0:
_turn(1,a,b,0);break;
case 1:
_turn(1,a,b,1);break;
case 2:
_reverse(1,a,b);break;
case 3:
ans=0;_count(1,a,b);printf("%d\n",ans);break;
case 4:
Node res=_query(1,a,b);
printf("%d\n",res.maxnum1);break;

}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: