bzoj2653
CLJ神牛的可持久化论文的题目,果然厉害
其实第一步能想到后面就还是很简单的
首先是二分答案,转化为判定性问题
然后对于区间内的数,比他大的标为1,小的标为-1
显然,如果存在一个左右端点符合的区间使得这个区间和大于等于0(因为这里中位数是向下取整)
那么中位数一定是大于等于这个数的,这并不难理解
下面我们就是要快速求出左端点在[a,b],右端点[c,d]的最大区间和
显然可以转化为rmax[a,b]+sum[b+1,c-1]+lmax[c,d];
这里我们不难想到对于每个数建立一个线段树
线段树就是以位置为索引的,记录着区间左最大,区间右最大和区间和
考虑到树的形态都是相同的,我们可以先对数进行排序,然后建立主席树
平时我们的主席树都是在每个位置上建立一棵以键值为索引的线段树,而这里刚好相反
二分答案后就对对应数的线段树求区间最大和
type node=record
lm,rm,l,r,s:longint;
end; var tree:array[..*] of node;
a,c,h:array[..] of longint;
q:array[..] of longint;
j,m,t,ans,n,mid,i,l,r,w:longint; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; procedure deal;
var i,j:longint;
begin
for i:= to do
for j:=i+ to do
if q[i]>q[j] then swap(q[i],q[j]);
end; procedure sort(l,r: longint);
var i,j,x,y: longint;
begin
i:=l;
j:=r;
x:=a[(l+r) shr ];
repeat
while a[i]<x do inc(i);
while x<a[j] do dec(j);
if not(i>j) then
begin
swap(c[i],c[j]);
swap(a[i],a[j]);
inc(i);
j:=j-;
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
procedure update(var a,b,c:node);
begin
a.s:=b.s+c.s;
a.lm:=max(b.lm,b.s+c.lm);
a.rm:=max(c.rm,c.s+b.rm);
end; function build(l,r:longint):longint;
var m,q:longint;
begin
inc(t);
if l=r then
begin
tree[t].s:=;
tree[t].lm:=;
tree[t].rm:=;
exit(t);
end
else begin
m:=(l+r) shr ;
q:=t;
tree[q].l:=build(l,m);
tree[q].r:=build(m+,r);
update(tree[q],tree[tree[q].l],tree[tree[q].r]);
exit(q);
end;
end; function work(l,r,last,x:longint):longint;
var m,q:longint;
begin
inc(t);
if l=r then
begin
tree[t].s:=-;
tree[t].lm:=-;
tree[t].rm:=-;
exit(t);
end
else begin
m:=(l+r) shr ;
q:=t;
if x<=m then
begin
tree[q].r:=tree[last].r;
tree[q].l:=work(l,m,tree[last].l,x);
end
else begin
tree[q].l:=tree[last].l;
tree[q].r:=work(m+,r,tree[last].r,x);
end;
update(tree[q],tree[tree[q].l],tree[tree[q].r]);
exit(q);
end;
end; function ask(l,r,x,ql,qr:longint):node; //传递整个node的的写法比我以前的写法要简单不少
var m:longint;
s,s1,s2:node;
begin
s.lm:=; s.rm:=; s.s:=;
if ql>qr then exit(s);
if (ql<=l) and (qr>=r) then exit(tree[x])
else begin
m:=(l+r) shr ;
if ql>m then exit(ask(m+,r,tree[x].r,ql,qr));
if qr<=m then exit(ask(l,m,tree[x].l,ql,qr));
s1:=ask(l,m,tree[x].l,ql,qr);
s2:=ask(m+,r,tree[x].r,ql,qr);
update(s,s1,s2);
exit(s);
end;
end; begin
readln(n);
for i:= to n do
begin
readln(a[i]);
c[i]:=i;
end;
sort(,n);
h[]:=build(,n);
for i:= to n do
h[i]:=work(,n,h[i-],c[i-]);
readln(m);
for i:= to m do
begin
for j:= to do
begin
read(q[j]);
q[j]:=(q[j]+ans) mod n+;
end;
readln;
deal;
l:=;
r:=n;
while l<=r do //二分答案
begin
mid:=(l+r) shr ;
w:=ask(,n,h[mid],q[],q[]).rm+ask(,n,h[mid],q[],q[]).lm+ask(,n,h[mid],q[]+,q[]-).s;
if w>= then
begin
ans:=a[mid];
l:=mid+;
end
else r:=mid-;
end;
writeln(ans);
end;
end.
bzoj2653的更多相关文章
- BZOJ2653 middle(二分答案+主席树)
与中位数有关的题二分答案是很常用的trick.二分答案之后,将所有大于它的看成1小于它的看成-1,那么只需要判断是否存在满足要求的一段和不小于0. 由于每个位置是1还是-1并不固定,似乎不是很好算.考 ...
- 【BZOJ2653】Middle(主席树)
[BZOJ2653]Middle(主席树) 题面 BZOJ 洛谷 Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你 ...
- BZOJ2653 middle 【主席树】【二分】*
BZOJ2653 middle Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样 ...
- 【BZOJ2653】middle 二分+可持久化线段树
[BZOJ2653]middle Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个 ...
- [bzoj2653][middle] (二分 + 主席树)
Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b ...
- 【BZOJ-2653】middle 可持久化线段树 + 二分
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1298 Solved: 734[Submit][Status][Discu ...
- bzoj2653: middle
首先,对于每个询问,我们二分答案 然后对于序列中大于等于中位数的数,我们把它们置为1,小于中位数的数,置为-1 那么如果一个区间和大于等于0,那么就资磁,否则就不滋磁 这个区间和呢,我们可以用主席树维 ...
- bzoj2653:middle
思路:首先容易想到二分答案,但如何去check呢,对于一段区间[l,r],把所有小于答案的都赋值为-1,大于等于它的都赋值为1,然后求左端点在[a,b],右端点在[c,d]的最大子串和即可(也就是区间 ...
- 【BZOJ2653】【主席树+二分】middle
Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b ...
随机推荐
- JS获取URL的参数
function request(paras) { var url = location.href; , url.length).split("&"); var paraO ...
- Oracle中的job(转载)
我们在项目开发中,常常会有一些复杂的业务逻辑.使用oracle的存储过程,可以大大减少java程序代码的编写工作量,而且存储过程执行在数据库上,这样可以利用oracle的良好性能支持,极大地提高程序执 ...
- (转) linux虚拟机中和主机三种网络连接方式的区别
在介绍网络模式之前,关于网络的几个简单命令的使用 ifup eth0 //启动网卡eth0 ifdown eth0 //关闭网卡eth0 /etc/network/interfaces //网络 ...
- WEB 中的一些名词解释
OOP: 面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一种计算机编程架构. AOP: AOP为Aspect Oriented Programmin ...
- js实现FileUpload选择图片后预览功能
当asp.net的FileUpload选择一个图片后不需要上传就能显示出图片的预览功能, 代码: <%@ Page Language="C#" AutoEventWireup ...
- 国内最简单的短视频SDK
最近阿里百川和趣拍一起合作推出了一个短视频SDK.之前很多厂商可能都是用的Vitamio的短视频SDK.之后我考察过,也做过一些调查,发现Vitamio真的奇贵无比,屌丝公司根本用不起,阿里和趣拍这下 ...
- SQL统计不重复字段的个数.
注意:下面的举例适用于ORCLE和MSSQL,不能在Access中使用. 语法 SELECT COUNT(DISTINCT column(s)) FROM table 举例 With this &qu ...
- xp和win 2003远程桌面强制进入命令
xp和win 2003远程桌面强制进入命令 注意:端口号也可以不写 如果是在win 2003里面进行踢人的话可以用命令: mstsc /console /v:172.25.100.27:3389 如果 ...
- Web.xml配置详解之context-param (加载spring的xml,然后初始化bean看的)
http://www.cnblogs.com/goody9807/p/4227296.html(很不错啊) 容器先加载spring的xml,然后初始化bean时,会为bean赋值,包括里面的占位符
- CATransform3DRotate 实现左右,上下翻转效果
CGFloat m34 = 800; CGFloat value = -40://(控制翻转角度) CGPoint point = CGPointMake(0.5, 0.5);//设定翻转时的 ...