bzoj1858
比较烦的线段树
首先询问3很弱智不说,
询问4以前做过类似的,好像是USACO月赛hotel那题类似,维护lmax,rmax,max三个域就可以了
操作0,操作1也很简单,仔细考虑一下就知道也是可以lazy tag的
重点是操作2,好像数据结构题中翻转总是一个难点
由于翻转影响对询问4影响较大(对询问3基本没什么影响)
我们考虑这次维护六个域lmax0,rmax0,max0,lmax1,rmax1 max1 分别表示在区间内0和1从左起最多连续几个,从右起最多连续几个,区间内最多连续几个
然后我们来考虑操作,首先难想到维护rev域表示区间是否翻转,lazy表示0表示全0,1表示全1,-1表示没有进行覆盖操作
操作0,1对操作2有强制性,只要执行操作0,1,就一定可以直接覆盖之前的操作
然后执行取反操作的时候,如果lazy<>-1 那么对lazy取反(0-->1 1-->0) 否则再对rev取反
type node=record
l,r,lm1,rm1,m1,lm0,rm0,m0,sum:longint;
end; var tree:array[..] of node;
lazy,a:array[..] of integer;
rev:array[..] of boolean;
ch,i,n,m,x,y:longint; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; procedure fill1(i:longint);
var l,r:longint;
begin
l:=tree[i].l;
r:=tree[i].r;
tree[i].sum:=r-l+;
tree[i].lm1:=r-l+;
tree[i].rm1:=r-l+;
tree[i].m1:=r-l+;
tree[i].lm0:=;
tree[i].rm0:=;
tree[i].m0:=;
end; procedure fill0(i:longint);
var l,r:longint;
begin
l:=tree[i].l;
r:=tree[i].r;
tree[i].sum:=;
tree[i].lm0:=r-l+;
tree[i].rm0:=r-l+;
tree[i].m0:=r-l+;
tree[i].lm1:=;
tree[i].rm1:=;
tree[i].m1:=;
end; procedure change(i:longint);
var l,r:longint;
begin
l:=tree[i].l;
r:=tree[i].r;
tree[i].sum:=(r-l+)-tree[i].sum;
swap(tree[i].m1,tree[i].m0);
swap(tree[i].lm1,tree[i].lm0);
swap(tree[i].rm1,tree[i].rm0);
end; procedure update(i:longint); //由下向上更新
var l,r,m,p:longint;
begin
l:=tree[i].l;
r:=tree[i].r;
m:=(l+r) shr ;
tree[i].sum:=tree[i*].sum+tree[i*+].sum;
//
tree[i].lm1:=tree[i*].lm1;
if tree[i*].lm1=m-l+ then
tree[i].lm1:=tree[i].lm1+tree[i*+].lm1; tree[i].rm1:=tree[i*+].rm1;
if tree[i*+].rm1=r-m then
tree[i].rm1:=tree[i].rm1+tree[i*].rm1; tree[i].m1:=max(tree[i].lm1,tree[i].rm1);
p:=max(tree[i*].rm1+tree[i*+].lm1,max(tree[i*].m1,tree[i*+].m1));
tree[i].m1:=max(p,tree[i].m1);
//
tree[i].lm0:=tree[i*].lm0;
if tree[i*].lm0=m-l+ then
tree[i].lm0:=tree[i].lm0+tree[i*+].lm0; tree[i].rm0:=tree[i*+].rm0;
if tree[i*+].rm0=r-m then
tree[i].rm0:=tree[i].rm0+tree[i*].rm0; tree[i].m0:=max(tree[i].lm0,tree[i].rm0);
p:=max(tree[i*].rm0+tree[i*+].lm0,max(tree[i*].m0,tree[i*+].m0));
tree[i].m0:=max(p,tree[i].m0);
end; procedure pushdown(i:longint); //传递标记
begin
if lazy[i]<>- then
begin
lazy[i*]:=lazy[i];
lazy[i*+]:=lazy[i];
if lazy[i]= then
begin
fill1(i*);
fill1(i*+);
end
else begin
fill0(i*);
fill0(i*+);
end;
lazy[i]:=-;
rev[i]:=false;
end;
if rev[i] then
begin
if lazy[i*]<>- then lazy[i*]:=-lazy[i*]
else rev[i*]:=not rev[i*];
if lazy[i*+]<>- then lazy[i*+]:=-lazy[i*+]
else rev[i*+]:=not rev[i*+];
change(i*+);
change(i*);
rev[i]:=false;
end;
end; procedure build(i,l,r:longint);
var m:longint;
begin
tree[i].l:=l;
tree[i].r:=r;
lazy[i]:=-;
if l=r then
begin
tree[i].sum:=a[l];
if a[l]= then
begin
tree[i].lm1:=;
tree[i].rm1:=;
tree[i].m1:=;
end
else begin
tree[i].lm0:=;
tree[i].rm0:=;
tree[i].m0:=;
end;
end
else begin
m:=(l+r) shr ;
build(i*,l,m);
build(i*+,m+,r);
update(i);
end;
end; procedure work(i,l,r:longint);
var m:longint;
begin
if (x<=l) and (y>=r) then
begin
if rev[i]=true then rev[i]:=false;
lazy[i]:=ch;
if ch= then fill1(i)
else fill0(i);
end
else begin
if (lazy[i]<>-) or (rev[i]) then pushdown(i);
m:=(l+r) shr ;
if x<=m then work(i*,l,m);
if y>=m+ then work(i*+,m+,r);
update(i);
end;
end; procedure reverse(i,l,r:longint);
var m:longint;
begin
if (x<=l) and (y>=r) then
begin
if lazy[i]<>- then lazy[i]:=-lazy[i]
else rev[i]:=not rev[i];
change(i);
end
else begin
if (lazy[i]<>-) or rev[i] then pushdown(i);
m:=(l+r) shr ;
if x<=m then reverse(i*,l,m);
if y>=m+ then reverse(i*+,m+,r);
update(i);
end;
end; function asksum(i,l,r:longint):longint;
var m,t:longint;
begin
if (x<=l) and (y>=r) then exit(tree[i].sum)
else begin
if (lazy[i]<>-) or rev[i] then pushdown(i);
m:=(l+r) shr ;
t:=;
if (x<=m) then t:=t+asksum(i*,l,m);
if y>=m+ then t:=t+asksum(i*+,m+,r);
update(i);
exit(t);
end;
end; function askmax(i,l,r:longint):longint;
var m,t,t1,t2:longint;
begin
if (x<=l) and (y>=r) then exit(tree[i].m1)
else begin
if (lazy[i]<>-) or rev[i] then pushdown(i);
m:=(l+r) shr ;
t1:=;
t2:=;
t:=;
if (x<=m) then t1:=askmax(i*,l,m);
if y>=m+ then t2:=askmax(i*+,m+,r);
if (x<=m) and (y>=m+) then t:=min(tree[i*].rm1,m-x+)+min(tree[i*+].lm1,y-m); //注意不能少考虑这种情况
t:=max(t,max(t1,t2));
update(i);
exit(t);
end;
end; begin
readln(n,m);
for i:= to n do
read(a[i]);
build(,,n); //初始化
for i:= to m do
begin
readln(ch,x,y);
inc(x);
inc(y);
if ch= then
work(,,n)
else if ch= then
work(,,n)
else if ch= then
reverse(,,n)
else if ch= then
writeln(asksum(,,n))
else if ch= then
writeln(askmax(,,n));
end;
end.
bzoj1858的更多相关文章
- 【BZOJ1858】序列操作(线段树)
[BZOJ1858]序列操作(线段树) 题面 BZOJ 题解 这题思路很简单,细节很烦,很码 维护区间翻转和区间赋值标记 当打到区间赋值标记时直接覆盖掉翻转标记 下放标记的时候先放赋值标记再放翻转标记 ...
- scoi2010&&bzoj1858序列操作
[题目描述] lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a ...
- 【BZOJ-1858】序列操作 线段树
1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1961 Solved: 991[Submit][Status ...
- BZOJ1858[Scoi2010]序列操作 题解
题目大意: 有一个01序列,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0:1 a b 把[a, b]区间内的所有数全变成1:2 a b 把[a,b]区间 ...
- bzoj1858: [Scoi2010]序列操作
lazy-tag线段树. #include<cstdio> #include<algorithm> #include<cstring> using namespac ...
- bzoj千题计划177:bzoj1858: [Scoi2010]序列操作
http://www.lydsy.com/JudgeOnline/problem.php?id=1858 2018 自己写的第1题,一遍过 ^_^ 元旦快乐 #include<cstdio> ...
- bzoj1858[Scoi2010]序列操作 线段树
1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 3079 Solved: 1475[Submit][Statu ...
- [待码][BZOJ1858]SCOI2010序列操作 jzyzoj1655
待码的线段树.....太长了看上去不是很想写 [ 什么破理由啊摔,不要脸 ] 嗯先水几道再写
- 【bzoj1858】[Scoi2010]序列操作 线段树区间合并
题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b ...
随机推荐
- nyoj89 汉诺塔(二)
题目网址 :http://acm.nyist.net/JudgeOnline/problem.php?pid=89 汉诺塔问题的经典结论: 把i个盘子从一个柱子整体移到另一个柱子最少需要步数是 2的i ...
- 学习笔记5_Day09_网站访问量统计小练习
练习:访问量统计 一个项目中所有的资源被访问都要对访问量进行累加! 创建一个int类型的变量,用来保存访问量,然后把它保存到ServletContext的域中,这样可以保存所有的Servlet都可以访 ...
- ORACLE 关连更新 update select
总结: 关键的地方是where 语句的加入. 在11G中, 如果不加11G , 或造成除匹配的行数更新为相应的值之后, 其余的会变成负数. 所以, 测试的办法就是: 先查看需要更新的数量即连接的数 ...
- C# 简单的图像边缘提取
博主做的很简单,大家看一看就好了...... 用到的算法是robert算子,这是一种比较简单的算法: f(x,y)=sqrt((g(x,y)-g(x+1,y+1))^2+(g(x+1,y)-g(x,y ...
- redis 在windows上运行
参考自:https://github.com/ServiceStack/redis-windows 1.用vagrant 运行redis的最后版本 1.1在windows上安装vagrant http ...
- win7音量控制图标不见了怎么办啦?
1.打开程序管理器(ctrl+alt+delete)2.在进程那里找到"explorer.exe",然后按结束进程(此时工具栏会消失)3.然后在文件(程序管理器左上角),点击&qu ...
- java面试入门总结
最近正好有时间空下来,前一段时间本来打算呢,写一写阶段的总结,今天就来谈谈吧.作为一个java入门小白,之前就职于浙江大华,是通过大华10月份秋季招聘通过大华的面试. 浙江大华校招采用模式是先笔试.再 ...
- Codevs 3233 古道
3233 古道 时间限制: 1 s 空间限制: 8000 KB 题目等级:**白银 Silver** [传送门](http://codevs.cn/problem/3233/) 题目描述 Descri ...
- IDE开发<LER-Studio>(1)::UI设计
LER-Studio主要使用Microsoft Ribbon界面(fluentUI),大致为Office 2007 black. 首先创建MFC程序,基于多文档视图,Ribbon界面,基类选择CVie ...
- hdu 1286 找新朋友 (欧拉函数)
Problem Description 新年快到了,"猪头帮协会"准备搞一个聚会,已经知道现有会员N人,把会员从1到N编号,其中会长的号码是N号,凡是和会长是老朋友的,那么该会员的 ...