bzoj 1858: [Scoi2010]序列操作 || 洛谷 P2572
记一下:线段树占空间是$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的更多相关文章
- (WAWAWAWAWAWA) BZOJ 1858: [Scoi2010]序列操作
二次联通门 : BZOJ 1858: [Scoi2010]序列操作 /* BZOJ 1858: [Scoi2010]序列操作 已经... 没有什么好怕的的了... 16K的代码... 调个MMP啊.. ...
- bzoj 1858: [Scoi2010]序列操作
1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MB 线段树,对于每个区间需要分别维护左右和中间的1和0连续个数,并在op=4时特殊 ...
- BZOJ 1858: [Scoi2010]序列操作( 线段树 )
略恶心的线段树...不过只要弄清楚了AC应该不难.... ---------------------------------------------------------------- #inclu ...
- bzoj 1858: [Scoi2010]序列操作【线段树】
合并中间那块的时候没取max--WAWAWA 在线段树上维护一堆东西,分别是len区间长度,sm区间内1的个数,ll0区间从左开始最长连续0,ml0区间中间最长连续0,rl0区间从右开始最长连续0,l ...
- 1858: [Scoi2010]序列操作
1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 3397 Solved: 1624 [Submit][Statu ...
- bzoj1858[Scoi2010]序列操作 线段树
1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 3079 Solved: 1475[Submit][Statu ...
- 【题解】Luogu P2572 [SCOI2010]序列操作
原题传送门:P2572 [SCOI2010]序列操作 这题好弱智啊 裸的珂朵莉树 前置芝士:珂朵莉树 窝博客里对珂朵莉树的介绍 没什么好说的自己看看吧 操作1:把区间内所有数推平成0,珂朵莉树基本操作 ...
- P2572 [SCOI2010]序列操作
对自己 & \(RNG\) : 骄兵必败 \(lpl\)加油! P2572 [SCOI2010]序列操作 题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要 ...
- BZOJ_1858_[Scoi2010]序列操作_线段树
BZOJ_1858_[Scoi2010]序列操作_线段树 Description lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询 ...
随机推荐
- Windows平台下Git(gitblit)服务器搭建
环境:Windows 10 专业版32位 因为公司服务器上已经搭了Visual SVN等,只好在Windows上搭个Git Server给大家用. 参考链接:http://www.cnblogs.co ...
- http://vdceye.com/ 全新页面上线
vdceye manager home page
- java SE基础(Collection接口概述)
Collection接口相关集成关系例如以下图 1. 关于可迭代接口(Iterable) 可迭代接口仅包括一个方法,返回一个在一组T类型元素上进行迭代的迭代器: public ...
- Nginx系列三 内存池的设计
Nginx的高性能的是用非常多细节来保证,epoll下的多路io异步通知.阶段细分化的异步事件驱动,那么在内存管理这一块也是用了非常大心血.上一篇我们讲到了slab分配器,我们能够能够看到那是对共享内 ...
- NS3网络仿真(12): ICMPv4协议
快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 ICMP的全称是 Internet ControlMessage Protocol . 其目的就是 ...
- IO获取指定目录及其目录下子目录
一.需求:获取指定目录下,指定扩展名的文件(包含子目录中的) 二.需要用到的方法 1.FilenameFilter :返回抽象路径名的定义中表示此抽象路径名的目录中的文件的数组. filter.ac ...
- win7 32位下安装MySQL出现的---1067系统错误---问题及解决
每次安装数据库,总是出现这样那样的问题.如今记录下来,供日后參考咯.... 下载的是解压缩-zip版本号的.安装配置教程參照洪哥笔记文章-<MySQL-5.6.13解压版(zip版)安装配置教程 ...
- [IT学习]Python如何处理异常特殊字符
欢迎访问www.cnblogs.com/viphhs A byte of Python<输入与输出>一节中有一个处理回文的小例子(io_input.py).作者留了个思考题. 如何将标点去 ...
- Codeforces Round #261 (Div. 2)——Pashmak and Graph
题目链接 题意: n个点.m个边的有向图.每条边有一个权值,求一条最长的路径,使得路径上边值严格递增.输出路径长度 )) 分析: 由于路径上会有反复点,而边不会反复.所以最開始想的是以边为状态进行DP ...
- YTU 2851: 数字游戏
2851: 数字游戏 时间限制: 1 Sec 内存限制: 128 MB 提交: 164 解决: 85 题目描述 输入若干个正整数,将其中能写成其它两个正整数的平方和的数输出来. 例,若输入的数中有 ...