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实战之02Hibernate-06处理并发
十三.处理并发 1.事务的隔离级别 不考虑隔离级别出现的问题: 脏读:一个线程中的事务读到了另外一个线程中未提交的数据. 不可重复读:一个线程中的事务读到了另外一个线程中提交的update(更新)的数 ...
- Poj 1001 / OpenJudge 2951 Exponentiation
1.链接地址: http://poj.org/problem?id=1001 http://bailian.openjudge.cn/practice/2951 2.题目: Exponentiatio ...
- ubuntu12.10设置禁止锁屏和屏幕常亮
1.System Settings -> Brightness and Lock -> Turn off screen... set to "Never" 进入ubun ...
- 关于php的认识和介绍
php的介绍: 什么是php? <1>:php是一个编程语言 <2>:php是处理php编程语言的一个软件.php语言必须运行在php软件上. 为什么要学习php? php可以 ...
- 排序算法SIX:冒泡排序BubbleSort
/** *冒泡排序: * 两个两个比较,一轮过后最大的排在了最后面 * n个数变为n-1个没排好的数 * 再进行一轮 * 第二大的排在了倒数第二个 * 以此类推 * 直到排到第一个为止 * * 弄两个 ...
- jQuery按钮复制文本内容
这种方法能保证文本内容被复制到windows剪切板,代码示例是复制url <!doctype html> <html> <head> <meta charse ...
- linux共享文件samba安装与java读取外部文件夹方法
测试环境RedHat 6.4 一.安装 samba组件安装: (1)首先用“rpm –qa |grep samba”命令检验系统samba服务是否安装. #rpm –qa |grep samba sa ...
- memcached完全剖析--1
memcached的基础 翻译一篇技术评论社的文章,是讲memcached的连载.fcicq同学说这个东西很有用,希望大家喜欢. 发表日:2008/7/2 作者:长野雅广(Masahiro Nagan ...
- 关于APP,原生和H5开发技术的争论
App的开发技术,目前流行的两种方式,原生和Html5.原生分了安卓平台和ios平台(还有小众的黑莓.死去的塞班就不说了),H5就是Html5. 目前争论不休的问题,在早先前争论CS,BS架构的软件系 ...
- Win2008 R2 IIS7.5+PHP5(FastCGI)+MySQL5环境搭建教程
现在很多朋友想尝试win2008 r2来跑web服务器,跟win2003相比界面差别有点大,有些人可能不太习惯,不过以后是趋势啊,这里简单分享下,方便需要的朋友 准备篇 一.环境说明: 操作系统:Wi ...