POJ2104 区间第k小
题意就是区间第k大……
题解:
前段时间用主席树搞掉了……
如今看到划分树,是在想来写一遍,结果18号对着学长的代码调了一上午连样例都没过,好桑心……
今天在做NOI2010超级钢琴,忽然发现用划分树很直观,果断决定再战划分树
对着网上的c++代码抄了一遍,A了,可是这编程复杂度有点高,忽然又看见盾哥的代码
很简短,和我原先的代码差不多,他怎么能A了呢……(后来发现区间第k小,我却写的第k大……sb啊)
考虑到盾哥的程序用到了离散化,因此没有考虑存在两个数相等的情况,这样就使代码减少很多
我报着试一试的心态把我认为肯定对的代码随机生成了几组大数据和盾哥的程序对拍,然后就对上了
好的,以后就用盾哥的程序
代码:
c++翻译来的:
var s,t:array[..,..] of longint;
a,rk:array[..] of longint;
i,n,m,x,y,k,j:longint;
procedure sort(l,r:longint);
var i,j,m,temp:longint;
begin
i:=l;j:=r;m:=a[(i+j)>>];
repeat
while a[i]<m do inc(i);
while a[j]>m do dec(j);
if i<=j then
begin
temp:=a[i];a[i]:=a[j];a[j]:=temp;
inc(i);dec(j);
end;
until i>j;
if i<r then sort(i,r);
if j>l then sort(l,j);
end;
procedure init;
begin
readln(n,m);
for i:= to n do read(a[i]);t[]:=a;
sort(,n);
end;
procedure build(h,l,r:longint);
var mid,i,lp,rp,lm:longint;
begin
mid:=(l+r)>>;lm:=mid-l+;lp:=l;rp:=mid+;
for i:=l to mid do
if a[i]<a[mid] then dec(lm);
for i:=l to r do
begin
if i=l then s[h,i]:= else s[h,i]:=s[h,i-];
if t[h,i]=a[mid] then
begin
if lm<> then
begin
dec(lm);inc(s[h,i]);t[h+,lp]:=t[h,i];inc(lp);
end
else begin t[h+,rp]:=t[h,i];inc(rp);end;
end
else
if t[h,i]<a[mid] then begin inc(s[h,i]);t[h+,lp]:=t[h,i];inc(lp);end
else begin t[h+,rp]:=t[h,i];inc(rp);end;
end;
if l=r then exit;
build(h+,l,mid);
build(h+,mid+,r);
end;
function find(h,l,r,x,y,k:longint):longint;
var mid,ll,rr:longint;
begin
if l=r then exit(t[h,l]);
mid:=(l+r)>>;
if l=x then ll:= else ll:=s[h,x-];rr:=s[h,y]-ll;
if rr>=k then exit(find(h+,l,mid,l+ll,l+ll+rr-,k))
else exit(find(h+,mid+,r,mid++x-l-ll,mid++y-l-ll-rr,k-rr));
end;
procedure main;
begin
build(,,n);
for i:= to m do
begin
readln(x,y,k);
writeln(find(,,n,x,y,k));
end;
end;
begin
init;
main;
end.
盾哥的:
program poj2104; const maxn=;
var
a,b:array[..maxn] of longint;
s,d:array[..,..maxn] of longint;
n,m,i,j,x,y,z,ls,rs,mid,p:longint; procedure sort(l,r:longint); var i,j,x,y:longint;
begin
i:=l;j:=r;x:=a[(i+j)>> ];
repeat
while b[a[i]]<b[x] do inc(i);
while b[a[j]]>b[x] do dec(j);
if i<=j then begin
y:=a[i];a[i]:=a[j];a[j]:=y;
inc(i);dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; procedure buildtree(h,l,r:longint);var mid:longint;
begin
if l=r then exit;
mid:=(l+r+)>> ;p:=;
for i:=l to r do
if d[h,i]<mid then begin
d[h+,l+p]:=d[h,i];
inc(p);s[h,i]:=p;
end else begin
d[h+,mid+i-l-p]:=d[h,i];
s[h,i]:=p;
end;
buildtree(h+,l,mid-);
buildtree(h+,mid,r);
end; function find(h,ll,rr,l,r,k:longint):longint;
begin
if l=r then exit(d[h,r]);
if l=ll then ls:= else ls:=s[h,l-];
rs:=s[h,r];mid:=(ll+rr+)>> ;
if rs-ls<k
then find:=find(h+,mid,rr,l-ll-ls+mid,r-ll-rs+mid,k-rs+ls)
else find:=find(h+,ll,mid-,ls+ll,rs+ll-,k);
end; begin
readln(n,m);
for i:= to n do begin read(b[i]);a[i]:=i; end;
sort(,n);
for i:= to n do d[,a[i]]:=i;
buildtree(,,n);
for i:= to m do begin
readln(x,y,z);
writeln(b[a[find(,,n,x,y,z)]]);
end;
end.
我最先抄的:
const maxn=+;
type arrtype=array[..maxn] of longint;
var s,z:array[..,..maxn] of longint;
a,b,rk:arrtype;
i,j,n,m,x,y,k:longint;
procedure sort(var a:arrtype;l,r:longint);
var i,j,m,temp:longint;
begin
i:=l;j:=r;m:=a[(i+j)>>];
repeat
while a[i]<m do inc(i);
while a[j]>m do dec(j);
if i<=j then
begin
temp:=a[i];a[i]:=a[j];a[j]:=temp;
temp:=rk[i];rk[i]:=rk[j];rk[j]:=temp;
inc(i);dec(j);
end;
until i>j;
if i<r then sort(a,i,r);
if j>l then sort(a,l,j);
end;
procedure init;
begin
readln(n,m);
for i:= to n do read(a[i]);readln;b:=a;
for i:= to n do rk[i]:=i;
sort(a,,n);
end;
procedure build(h,l,r:longint);
var i,p,mid:longint;
begin
mid:=(l+r)>>;p:=;
for i:=l to r do
if z[h,i]<=mid then
begin
z[h+,l+p]:=z[h,i];
inc(p);
s[h,i]:=p;
end
else
begin
z[h+,mid++i-p-l]:=z[h,i];
s[h,i]:=p;
end;
if l=r then exit;
build(h+,l,mid);
build(h+,mid+,r);
end;
function find(h,l,r,x,y,k:longint):longint;
var ll,rr,mid:longint;
begin
if l=r then exit(z[h,l]);
mid:=(l+r)>>;
if l=x then ll:= else ll:=s[h,x-];rr:=s[h,y];
if rr-ll>=k then exit(find(h+,l,mid,l+ll,l+rr-,k))
else exit(find(h+,mid+,r,mid++x-l-ll,mid++y-l-rr,k-(rr-ll)));
end;
procedure main;
begin
for i:= to n do z[,rk[i]]:=i;
build(,,n);
for i:= to m do
begin
readln(x,y,k);
writeln(b[rk[find(,,n,x,y,k)]]);
end;
end;
begin
init;
main;
end.
盾哥的代码风格确实比我好很多,值得学习
UPD:
c++
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#define inf 1000000000
#define maxn 100000+100
#define maxm 100000
using namespace std;
int n,m,a[maxn],sa[maxn],t[][maxn],s[][maxn];
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void build(int h,int l,int r)
{
int mid=(l+r)>>,num=;
for(int i=l;i<=r;i++)
if (t[h][i]<=mid)
{
t[h+][l+num]=t[h][i];
s[h][i]=++num;
}
else
{
t[h+][mid++i-l-num]=t[h][i];
s[h][i]=num;
}
if(l==r)return;
build(h+,l,mid);
build(h+,mid+,r);
}
int find(int h,int l,int r,int x,int y,int k)
{
if(l==r)return t[h][l];
int mid=(l+r)>>,ll,rr;
ll=(l==x)?:s[h][x-];rr=s[h][y];
if(rr-ll>=k) return find(h+,l,mid,l+ll,l+rr-,k);
else return find(h+,mid+,r,mid++x-l-ll,mid++y-l-rr,k-(rr-ll));
}
bool cmp(int x,int y)
{
return a[x]<a[y];
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=read();m=read();
for(int i=;i<=n;i++){a[i]=read();sa[i]=i;}
sort(sa+,sa+n+,cmp);
for(int i=;i<=n;i++)t[][sa[i]]=i;
build(,,n);
for(int i=;i<=m;i++)
{
int x,y,k;
x=read();y=read();k=read();
printf("%d\n",a[sa[find(,,n,x,y,k)]]);
}
return ;
}
POJ2104 区间第k小的更多相关文章
- POJ2104 K-th Number —— 区间第k小 整体二分
题目链接:https://vjudge.net/problem/POJ-2104 K-th Number Time Limit: 20000MS Memory Limit: 65536K Tota ...
- 主席树总结(经典区间第k小问题)(主席树,线段树)
接着上一篇总结--可持久化线段树来整理吧.点击进入 这两种数据结构确实有异曲同工之妙.结构是很相似的,但维护的主要内容并不相同,主席树的离散化.前缀和等思想也要更难理解一些. 闲话 话说刚学习主席树的 ...
- ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解
题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...
- 【XSY2720】区间第k小 整体二分 可持久化线段树
题目描述 给你你个序列,每次求区间第\(k\)小的数. 本题中,如果一个数在询问区间中出现了超过\(w\)次,那么就把这个数视为\(n\). 强制在线. \(n\leq 100000,a_i<n ...
- A - 低阶入门膜法 - K-th Number (主席树查询区间第k小)
题目链接:https://cn.vjudge.net/contest/284294#problem/A 题目大意:主席树查询区间第k小. 具体思路:主席树入门. AC代码: #include<i ...
- HDU 2665.Kth number 区间第K小
Kth number Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- POJ 2014.K-th Number 区间第k小 (归并树)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 57543 Accepted: 19893 Ca ...
- Dynamic Rankings || 动态/静态区间第k小(主席树)
JYF大佬说,一星期要写很多篇博客才会有人看 但是我做题没有那么快啊QwQ Part1 写在前面 区间第K小问题一直是主席树经典题=w=今天的重点是动态区间第K小问题.静态问题要求查询一个区间内的第k ...
- 少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小
少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小 有一道题(BZOJ 1901)是这样的:n个数,m个询问,询问有两种:修改某个数/询问区间第k小. 不带修改的区间第k小用主席树很好写 ...
随机推荐
- Java实战之04JavaWeb-04JSP、EL表达式、JSTL标签库
一.jsp部分 只要是与页面显示相关的都是重点 1.jsp的脚本 <%java代码%>:被翻译到service方法内部,局部变量,局部的功能 <%=表达式或变量%>:翻译成se ...
- Unity中使物体自动寻路的方法
在做一个FPS游戏时,需要敌方自动找到玩家方位并向玩家移动,在查找资料(并走了不少坑)后,我试了三个方法,经测试,这三个方法都能实现自动寻路功能. 方法一:使用Mathf.Lerp()方法 代码很简单 ...
- Walkthrough: Creating and Using a Dynamic Link Library (C++)
Original Link: http://msdn.microsoft.com/zh-cn/library/ms235636.aspx Following content is only used ...
- MFC通过ADO操作Access数据库
我在<VC知识库在线杂志>第十四期和第十五期上曾发表了两篇文章——“直接通过ODBC读.写Excel表格文件”和“直接通过DAO读.写Access文件”,先后给大家介绍了ODBC和DAO两 ...
- Struts2文件上传方式与上传失败解决方式
首先将几个对象弄出来第一个 上传页面第二个 上传action第三个 startut2配置文件 我的文字描述不是很好,但是终归是自己写出来的,后来我在网上看到一篇关于文件上传描述的非常清楚的文章, 链接 ...
- python 自动化之路 day 09 进程、线程、协程篇
本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者 ...
- Linux作业控制
在Linux中,利用Shell的作业控制是比较常用的操作,在这一节中我们将探究作业控制相关的操作.为了方便我们查看区分不同的进行,我们编写如下程序,其功能是每间隔2秒输出一次自己的编号. /* ** ...
- json 包含字段及函数的写法
在javascript中写类有多种方式: 1.function()中嵌套function; 2.prototype的方式 ,3.json的方式,如下: <script language=&quo ...
- Django视图与网址传参
目的:采用/add?a=1&b=2 这样get/post方法进行 修改一下mysite/views.py文件 from django.shortcuts import renderfrom ...
- 【python】Windows安装Beautiful Soup
环境:win10,python 3.5,Beautiful Soup 4.1 步骤1:设定python为系统环境变量,具体设置如下图,在文本后加上";C:\Python35;C:\Pyt ...