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,现在对于这个序列有五种变换操作和询 ...
随机推荐
- 使用7zip压解各种文件的经常使用命令
7zip简单介绍 格式支持 压缩解压缩 仅支持解压缩 安装 Debian Ubuntu ArchLinux 使用 打包 解压 列出文件的信息列表 检查包的完整性 更新压缩包 删除包里的文件 7zip简 ...
- 24Web前端架构
近来都是接触前端.所以学多点这方面的东西,虽说有实战到项目里面去了,但可能还没走到所谓正确的道路上去.欢迎交流. 转载请说明来着:http://blog.csdn.net/wowkk -------- ...
- C语言细节笔记2
C语言常见问题笔记: 1. 指针的声明 char * p1, p2; p1 是一个指向char类型的指针,而p2是一个char类型变量 这是由于 * 并不是基本类型的一部分,而是包含 ...
- android 开发中用到的工具-持续更新(码农必看)
1. vim 单文件查看改动利器(一直使用支持各种编码各种文件,各种插件),欢迎下载笔者插件 git clone https://github.com/green130181/vim-conf.git ...
- Nginx系列三 内存池的设计
Nginx的高性能的是用非常多细节来保证,epoll下的多路io异步通知.阶段细分化的异步事件驱动,那么在内存管理这一块也是用了非常大心血.上一篇我们讲到了slab分配器,我们能够能够看到那是对共享内 ...
- 【bzoj1015】【JSOI2008】【星球大战】【并查集+离线】
Description 非常久曾经.在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器.并攻下了星系中差点儿全部的星球.这些星球 ...
- 百度Fex webuploader.js上传大文件失败
项目上用百度webuploader.js上传文件,option选项里面已经设置单个文件大小,但是上传低于此阈值的文件时仍然不成功. 我现在的理解是,框架是将文件post到后台服务器端的.. 百度发现是 ...
- 如何快速定位JVM中消耗CPU最多的线程? Java 性能调优
https://mp.weixin.qq.com/s/ZqlhPC06_KW6a9OSgEuIVw 上面的线程栈我们注意到 nid 的值其实就是线程 ID,它是十六进制的,我们将消耗 CPU 最高的线 ...
- DataTabless Add rows
参考官网案例:https://datatables.net/examples/api/add_row.html JS: $(document).ready(function() { var t ...
- ios移动端浏览器点击事件失效的解决方案
点击事件失效的原因可能是因为,你用了事件代理了, 比如这样 $(document).on("click",".fd",function(){ }) 这段代码在安 ...