poj2761
表面上看是主席树之类的区间k大
实际上,除了主席树,还可以测各种结构
因为题目中说,任意区间不会完全包含
于是,我们把区间按左端点排序,依次添加,用平衡树求当前的k大
每个狗最多被添加一次,删除一次
所以复杂度为O(nlogn)
被来写的是splay,结果一直WA到死
结果改成treap,第一次写就1Y了,不错
不过调treap需要把一组数据跑很多遍(至少我是这么认为的)
以免出现rp过好导致错误的程序跑对……
const rd=;
type node=record
x,y,num,k:longint;
end;
var ans,pretty,fa,count,key,b:array[..] of longint;
son:array[..,..] of longint;
a:array[..] of node;
p,j,root,n,q,i,t,s:longint; procedure update(i:longint);
begin
count[i]:=count[son[i,]]+count[son[i,]]+;
end; function find(x:longint):longint;
var p:longint;
begin
p:=root;
repeat
if b[p]=x then exit(p);
if b[p]>x then p:=son[p,]
else p:=son[p,];
until false;
end; function kth(x:longint):longint; //找k大
var p:longint;
begin
p:=root;
while true do
begin
if count[son[p,]]+=x then exit(p);
if count[son[p,]]+>x then p:=son[p,]
else begin
x:=x-count[son[p,]]-;
p:=son[p,];
end;
end;
end; procedure clear(i:longint);
begin
count[i]:=;
son[i,]:=;
son[i,]:=;
fa[]:=;
count[]:=;
end; procedure rotate(x,w:longint); //基本的BST左右旋,和splay是一样的
var y:longint;
begin
y:=fa[x];
if fa[y]= then root:=x;
if fa[y]<> then
begin
if son[fa[y],]=y then son[fa[y],]:=x
else son[fa[y],]:=x;
end;
fa[x]:=fa[y];
son[y,-w]:=son[x,w];
fa[son[x,w]]:=y;
son[x,w]:=y;
fa[y]:=x;
update(y);
update(x);
end; procedure swap(var a,b:node);
var c:node;
begin
c:=a;
a:=b;
b:=c;
end; procedure up(i:longint); //类似堆的上浮操作
var j:longint;
begin
j:=fa[i];
while j<> do
begin
if key[i]<key[j] then
begin
if son[j,]=i then rotate(i,)
else rotate(i,);
end
else break;
j:=fa[i];
end;
if j= then root:=i;
end; procedure sift(i:longint); //类似堆的下沉操作
var j1,j2:longint;
begin
repeat
j1:=son[i,]; //选择较小的那个孩子旋转,使下沉后还能满足小根堆的性质
j2:=son[i,];
if (j1=) and (j2=) then break;
if (j1=) then
rotate(j2,)
else if (j2=) then
rotate(j1,)
else begin
if key[j1]>key[j2] then rotate(j2,) else rotate(j1,);
end;
until false;
end; procedure sort(l,r: longint);
var i,j,x,y: longint;
begin
i:=l;
j:=r;
x:=a[(l+r) shr ].x;
repeat
while (a[i].x<x) do inc(i);
while (x<a[j].x) do dec(j);
if not(i>j) then
begin
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 insert(x:longint);
var p:longint;
begin
inc(t);
inc(s);
clear(t);
key[t]:=trunc(random(rd)); //随机生成一个优先级,这个优先级满足小根堆的性质
b[t]:=x;
if root= then
begin
root:=t;
fa[t]:=;
end
else begin
p:=root; //先插入到treap中
repeat
inc(count[p]);
if b[p]>x then
begin
if son[p,]= then break;
p:=son[p,];
end
else begin
if son[p,]= then break;
p:=son[p,];
end;
until false;
fa[t]:=p;
if b[p]>x then son[p,]:=t else son[p,]:=t;
up(t); //调整treap
end;
end; procedure delete(x:longint);
var i,p:longint;
begin
i:=find(x);
key[i]:=; //只是为了清楚,treap删除是把当前节点旋转到叶节点
dec(s);
sift(i);
p:=i;
while p<>root do //注意删除时要更改它的父亲(祖先)的子树规模
begin
dec(count[fa[p]]);
p:=fa[p];
end;
if son[fa[i],]=i then son[fa[i],]:=
else son[fa[i],]:=;
count[i]:=;
key[i]:=;
b[i]:=;
fa[i]:=;
if s= then root:=;
end; begin
randomize;
readln(n,q);
for i:= to n do
read(pretty[i]);
readln;
for i:= to q do
begin
readln(a[i].x,a[i].y,a[i].k);
a[i].num:=i;
end;
count[]:=;
sort(,q);
root:=;
t:=;
for i:=a[].x to a[].y do
insert(pretty[i]);
ans[a[].num]:=b[kth(a[].k)];
for i:= to q do //按顺序一次添加删除
begin
if a[i].x>a[i-].y then
begin
root:=;
t:=;
s:=;
fillchar(fa,sizeof(fa),);
fillchar(son,sizeof(son),);
fillchar(count,sizeof(count),);
fillchar(b,sizeof(b),);
fillchar(key,sizeof(key),);
for j:=a[i].x to a[i].y do
begin
insert(pretty[j]);
end;
end
else begin
for j:=a[i-].y+ to a[i].y do
insert(pretty[j]);
for j:=a[i-].x to a[i].x- do
begin
delete(pretty[j]);
end;
end;
p:=kth(a[i].k);
ans[a[i].num]:=b[p];
end;
for i:= to q do
writeln(ans[i]);
end.
poj2761的更多相关文章
- 【poj2761】 Feed the dogs
http://poj.org/problem?id=2761 (题目链接) 题意 求区间第K大. Solution 和poj2104一模一样. 主席树代码 // poj2761 #include< ...
- 【莫队算法】【权值分块】poj2104 K-th Number / poj2761 Feed the dogs
先用莫队算法保证在询问之间转移的复杂度,每次转移都需要进行O(sqrt(m))次插入和删除,权值分块的插入/删除是O(1)的. 然后询问的时候用权值分块查询区间k小值,每次是O(sqrt(n))的. ...
- poj2761静态区间第k大
例题:poj2761 题目要求:给定一个长度为n的序列,给定m个询问,每次询问求[l,r]区间内的第k大: 对于这道题目来说,很多算法都可以使用,比如说树套树(一个负责划分区间,一个负责维护这段区间内 ...
- [POJ2761] Feed the dogs (Treap)
题目链接:http://poj.org/problem?id=2761 题目大意:给你n个数,m次查询,m次查询分别是a,b,k,查询下表从a到b的第k小元素是哪个.这m个区间不会互相包含. Trea ...
- [主席树]HDOJ2665 && POJ2104 && POJ2761
主席树真是神奇的物种! Orz一篇资料 题意:给n.m 下面有n个数 (编号1到n) 有m个询问,询问的是上面的数的编号在[l,r]之间第k小的数 n.m的范围都是$10^5$ 是主席树的入门题 ...
- 【POJ2761】【区间第k大】Feed the dogs(吐槽)
Description Wind loves pretty dogs very much, and she has n pet dogs. So Jiajia has to feed the dogs ...
- 【POJ2761】【fhq treap】A Simple Problem with Integers
Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...
- poj2761(treap入门)
给n个数,然后m个询问,询问任意区间的第k小的数,特别的,任意两个区间不存在包含关系, 也就是说,将所有的询问按L排序之后, 对于i<j , Li < Lj 且 Ri < Rj ...
- [POJ2761]Feed the dogs
Problem 查询区间第k大,但保证区间不互相包含(可以相交) Solution 只需要对每个区间左端点进行排序,那它们的右端点必定单调递增,不然会出现区间包含的情况. 所以我们暴力对下一个区间加上 ...
随机推荐
- PHP实现冒泡算法
<?php //php函数:count($arr)返回array的数值总数. function bubble_sort($arr){ for ($i = 6;$i > 0;$i --){ ...
- 转 IHttpModule不起作用
在 Visual Studio 中,测试 IHttpModule(httpModules) 正常,但是放到服务器上去就不起作用了,这多半得多服务器 IIS 配置入手. 一.看“应用程序池”的“托管管道 ...
- 1.JSP 简介及工作原理
1.JSP 简介 JSP(Java Server Pages)是由Sun Microsystems公司倡导.许多公司参与一起建立的一种动态网页技术标准.JSP技术有点类似ASP技术,它是在传统的网页H ...
- JavaScript技巧45招
原文:45 Useful JavaScript Tips, Tricks and Best Practices作者:Saad Mousliki 在这篇文章里,我将分享一些JavaScript的技巧.秘 ...
- Keil V4.72升级到V5.1X之后
问题描述 Keil V4.72升级到V5.1x之后,原来编译通过的工程,出现了如下错误: .\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\STM32f ...
- 【学习总结】【多线程】 线程 & 进程 & NSThread(多线程的一套API)
一.进程和线程 1.什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开 Chrome.Xcode,系统就会分别启动2个进 ...
- dnf的动画脚本研究
. 1.0x00 : 帧数 int16 2.0x02 : 总为1(?) int16 3.0x04 : 资源文件名长度 int32 4.长度+1 : 0,1(未知用 ...
- 扩展ExtJs 4.2.1 htmleditor 添加图片功能
做项目的时候遇到这样一个问题,因为我是用ExtJs做的后台管理框架,所以当我使用ExtJs htmleditor 控件 的时候,发现没有图片上传的功能,于是我打算在网上找找有关的文章,居然真有人写过, ...
- DXperience-12.1.5 官网下载+注册破解+帮助文档
安装包 DXperience 12.1.5 Universal 帮助文档: DXperienceHelp2010 DXperienceHelp2010-12.1.5.exe DXperienceHel ...
- 然爸读书笔记(2013-4)----打造facebook
扎克伯格的真实一面 (1)在公司内部知无不言,扎克伯格在公司内部问答时间.尽可能回答员工的任何问题,保持足够的透明度. (2)员工只有做到对外守口如瓶,我们才能做到对内知无不言. (3)faceboo ...