记一下:线段树占空间是$2^{ceil(log2(n))+1}$

这个就是一个线段树区间操作题,各种标记的设置、转移都很明确,只要熟悉这类题应该说是没有什么难度的。

由于对某区间set之后该区间原先待进行的取反操作失效(被覆盖),因此规定tag同时存在时set的标记先进行操作,这样对区间加上set标记时要去掉原有的取反标记。

对于操作4,线段树上每个区间维护6个值,分别表示:该区间最多的连续0/1,从左侧数起/从右侧数起/其中任意位置。题目中不问连续0,为什么连续0也要维护呢?这是为了在进行取反操作时,O(1)完成标记的维护(直接交换对0、1维护的3个值就行了)。

对于操作3,线段树上每个区间维护该区间1的个数。此时不需要额外记录0的个数,0的个数可以由区间总数-1的个数得到。

规定:set的标记为-1时表示不需要set操作,为0/1时表示需要set为该标记的值。

注意一点:对于取反的tag,每次取反操作的时候都是将tag取反,而不是置为1,不然在同一个位置取反两次就不对了。

各个标记含义同普通线段树:当前节点已经操作,其所有(任意级的)子节点待操作。维护的时候转移都是递推,细的就不讲了,有点多,要细心比对。

然而...

感觉自己药丸啊...调了三个小时才调出来,各种各样诡异的错误...如果省选考这个肯定没法做了..

幸好这个样例够强。。有一些奇怪的错误通过样例就查出来了,过了样例就1A了,不然真的不知道要调到什么时候。。。

note:以下程序中打了注释的语句都是错过的。。。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define mid ((l+r)>>1)
#define lc (num<<1)
#define rc (num<<1|1)
using namespace std;
struct Th
{
int a,b,c;
bool d;//是否全部是1
int len;
Th(int aa=,int bb=,int cc=,bool dd=,int ll=):a(aa),b(bb),c(cc),d(dd),len(ll){}
};
int num1[],maxnum[][][],settag[];
bool revtag[];
int n,m;
//定义tag同时存在时settag先进行操作
int a[];
int L,R,x;
//maxnum[][0/1][0/1/2]表示最多的连续0/1,接左侧/接右侧/中间
void pd(int l,int r,int num)
{
if(settag[num]!=-)
{
num1[lc]=settag[num]*(mid-l+);
maxnum[lc][][]=maxnum[lc][][]=maxnum[lc][][]=(-settag[num])*(mid-l+);
maxnum[lc][][]=maxnum[lc][][]=maxnum[lc][][]=settag[num]*(mid-l+);
num1[rc]=settag[num]*(r-mid);
maxnum[rc][][]=maxnum[rc][][]=maxnum[rc][][]=(-settag[num])*(r-mid);
maxnum[rc][][]=maxnum[rc][][]=maxnum[rc][][]=settag[num]*(r-mid);
revtag[lc]=revtag[rc]=;
settag[lc]=settag[rc]=settag[num];
settag[num]=-;
}
if(revtag[num])
{
num1[lc]=mid-l+-num1[lc];
num1[rc]=r-mid-num1[rc];
swap(maxnum[lc][][],maxnum[lc][][]);
swap(maxnum[lc][][],maxnum[lc][][]);
swap(maxnum[lc][][],maxnum[lc][][]);
swap(maxnum[rc][][],maxnum[rc][][]);
swap(maxnum[rc][][],maxnum[rc][][]);
swap(maxnum[rc][][],maxnum[rc][][]);
revtag[lc]^=;revtag[rc]^=;
revtag[num]=;
}
}
void update(int l,int r,int num)
{
num1[num]=num1[lc]+num1[rc];
maxnum[num][][]=maxnum[lc][][];
if(num1[lc]==) maxnum[num][][]=(mid-l+)+maxnum[rc][][];
maxnum[num][][]=maxnum[rc][][];
if(num1[rc]==) maxnum[num][][]=(r-mid)+maxnum[lc][][];
maxnum[num][][]=maxnum[lc][][];
if(num1[lc]==mid-l+) maxnum[num][][]=(mid-l+)+maxnum[rc][][];
maxnum[num][][]=maxnum[rc][][];
if(num1[rc]==r-mid) maxnum[num][][]=(r-mid)+maxnum[lc][][];
maxnum[num][][]=max(max(maxnum[lc][][],maxnum[rc][][]),maxnum[lc][][]+maxnum[rc][][]);
maxnum[num][][]=max(max(maxnum[lc][][],maxnum[rc][][]),maxnum[lc][][]+maxnum[rc][][]);
}
void build(int l,int r,int num)
{
if(l==r)
{
num1[num]=(a[l]==);
maxnum[num][][]=maxnum[num][][]=maxnum[num][][]=(a[l]==);
maxnum[num][][]=maxnum[num][][]=maxnum[num][][]=(a[l]==);
settag[num]=-;
return;
}
build(l,mid,lc);
build(mid+,r,rc);
settag[num]=-;update(l,r,num);
}
void setto(int l,int r,int num)
{
if(L<=l&&r<=R)
{
revtag[num]=;settag[num]=x;
num1[num]=x*(r-l+);//mid-l+1
maxnum[num][][]=maxnum[num][][]=maxnum[num][][]=(-x)*(r-l+);//mid-l+1
maxnum[num][][]=maxnum[num][][]=maxnum[num][][]=x*(r-l+);//mid-l+1
return;
}
pd(l,r,num);
if(L<=mid) setto(l,mid,lc);
if(mid<R) setto(mid+,r,rc);
update(l,r,num);
}
void revx(int l,int r,int num)
{
if(L<=l&&r<=R)
{
revtag[num]^=;
num1[num]=r-l+-num1[num];
swap(maxnum[num][][],maxnum[num][][]);
swap(maxnum[num][][],maxnum[num][][]);
swap(maxnum[num][][],maxnum[num][][]);
return;
}
pd(l,r,num);
if(L<=mid) revx(l,mid,lc);
if(mid<R) revx(mid+,r,rc);
update(l,r,num);
}
int query1(int l,int r,int num)
{
if(L<=l&&r<=R) return num1[num];
pd(l,r,num);
int ans=;
if(L<=mid) ans+=query1(l,mid,lc);
if(mid<R) ans+=query1(mid+,r,rc);
return ans;
}
Th query2(int l,int r,int num)
{
//if(L<=l&&r<=R) return Th(maxnum[num][1][0],maxnum[num][1][1],maxnum[num][1][2],num1[num]==r-l+1,1);
if(L<=l&&r<=R) return Th(maxnum[num][][],maxnum[num][][],maxnum[num][][],num1[num]==r-l+,r-l+);//num1[num]==1
pd(l,r,num);
Th ans,t1,t2;
if(L<=mid) t1=query2(l,mid,lc);
if(mid<R) t2=query2(mid+,r,rc);
ans.a=t1.a;
//if(t1.d||t1.len==0) ans.a=t1.len+t2.a;
if(t1.d) ans.a=t1.len+t2.a;
ans.b=t2.b;
//if(t2.d||t2.len==0) ans.b=t2.len+t1.b;
if(t2.d) ans.b=t2.len+t1.b;
ans.c=max(max(t1.c,t2.c),t1.b+t2.a);
ans.d=t1.d&&t2.d;
ans.len=t1.len+t2.len;
return ans;
}
int main()
{
int i,idx;Th ttt;
scanf("%d%d",&n,&m);
for(i=;i<=n;i++) scanf("%d",&a[i]);
build(,n,);
for(i=;i<=m;i++)
{
scanf("%d%d%d",&idx,&L,&R);L++,R++;
if(idx==) x=,setto(,n,);
else if(idx==) x=,setto(,n,);
else if(idx==) revx(,n,);
else if(idx==) printf("%d\n",query1(,n,));
else if(idx==) {ttt=query2(,n,);printf("%d\n",max(max(ttt.a,ttt.b),ttt.c));}
}
return ;
}

bzoj 1858: [Scoi2010]序列操作 || 洛谷 P2572的更多相关文章

  1. (WAWAWAWAWAWA) BZOJ 1858: [Scoi2010]序列操作

    二次联通门 : BZOJ 1858: [Scoi2010]序列操作 /* BZOJ 1858: [Scoi2010]序列操作 已经... 没有什么好怕的的了... 16K的代码... 调个MMP啊.. ...

  2. bzoj 1858: [Scoi2010]序列操作

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MB 线段树,对于每个区间需要分别维护左右和中间的1和0连续个数,并在op=4时特殊 ...

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

    略恶心的线段树...不过只要弄清楚了AC应该不难.... ---------------------------------------------------------------- #inclu ...

  4. bzoj 1858: [Scoi2010]序列操作【线段树】

    合并中间那块的时候没取max--WAWAWA 在线段树上维护一堆东西,分别是len区间长度,sm区间内1的个数,ll0区间从左开始最长连续0,ml0区间中间最长连续0,rl0区间从右开始最长连续0,l ...

  5. 1858: [Scoi2010]序列操作

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 3397 Solved: 1624 [Submit][Statu ...

  6. bzoj1858[Scoi2010]序列操作 线段树

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 3079  Solved: 1475[Submit][Statu ...

  7. 【题解】Luogu P2572 [SCOI2010]序列操作

    原题传送门:P2572 [SCOI2010]序列操作 这题好弱智啊 裸的珂朵莉树 前置芝士:珂朵莉树 窝博客里对珂朵莉树的介绍 没什么好说的自己看看吧 操作1:把区间内所有数推平成0,珂朵莉树基本操作 ...

  8. P2572 [SCOI2010]序列操作

    对自己 & \(RNG\) : 骄兵必败 \(lpl\)加油! P2572 [SCOI2010]序列操作 题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要 ...

  9. BZOJ_1858_[Scoi2010]序列操作_线段树

    BZOJ_1858_[Scoi2010]序列操作_线段树 Description lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询 ...

随机推荐

  1. poj 3468 A Simple Problem with Integers(线段树、延迟更新)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 74705   ...

  2. Openwrt 安装软件到U盘或硬盘

    http://blog.licess.org/openwrt-install-software-to-udisk-harddisk/ 运行一个多月的DDNAS被结婚来玩的小孩给关了,于是趁机更新了一下 ...

  3. 弄技术要弄通-公司reis的pub/sub怎么使用的呢?

    Pub/Sub in Redis using PHP Posted on November 14, 2011by xmeng I would like to put an example togeth ...

  4. CentOS 更改Apache默认网站目录

    http://www.osyunwei.com/archives/789.html引言:Apache默认的网站目录是在/var/www/html, 现在要把网站目录更改到/home/wwwroot/w ...

  5. eclipse Alt+/ 不能提示

    普通情况下alt+/有代码提示作用,还有代码提示的快捷代码也不是alt+/,因此要恢复代码提示用alt+/.须要做两件事.  在 Window - Preferences - General - Ke ...

  6. Windows7 64bits下安装TensorFlow GPU版本(图文详解)

    不多说,直接上干货! Installing TensorFlow on Windows的官网 https://www.tensorflow.org/install/install_windows 首先 ...

  7. Repeater控件前台复杂逻辑判断

    虽然现在开发大都是前后台ajax的方式,但是还有部分项目用后台cs代码+服务器控件开发的方式,小弟今天就遇到了一个 repeater显示列表,有一个字段是state状态,数据库里面存的是0 1 2类似 ...

  8. 更改Mysql登录密码

    版本号49之前的跨域设置 在Windows命令行下修改mysql数据库密码步骤如下: 1.通过dos命令进入mysql的bin目录: 2.输入“mysql -uroot -p”,回车进入mysql命令 ...

  9. C项目实践--图书管理系统(1)

    1.功能需求分析 图书管理系统主要用于对大量的图书信息,包括书名.作者.出版社.出版日期.ISBN(书号)等进行增.删.改.查以及保存等操作.同时也包括对用户的管理,用户包括管理员和普通用户两种权限, ...

  10. go---weichart个人对Golang中并发理解

    个人觉得goroutine是Go并行设计的核心,goroutine是协程,但比线程占用更少.golang对并发的处理采用了协程的技术.golang的goroutine就是协程的实现. 十几个gorou ...