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小用主席树很好写 ...
随机推荐
- hdu 1250 Hat's Fibonacci(高精度数)
// 继续大数,哎.. Problem Description A Fibonacci sequence is calculated by adding the previous two membe ...
- PHP连接sqlserver的两种方法,向sqlserver2000中写入数据,中文乱码
项目环境是php5.3.28 项目用的ThinkPHP3.2.3 已经mysql5.5数据库,要和另一个项目对接,需要连接sqlsever2000数据库进行一些操作. 第一种用php自带扩展连接数据 ...
- call_user_func
(PHP 4, PHP 5) call_user_func — 把第一个参数作为回调函数调用 mixed call_user_func ( callable $callback [, mixed $p ...
- Android开发系列之搭建开发环境
接触Android好久了,记得09年刚在中国大陆有点苗头的时候,我就知道了google有个Android,它是智能机操作系统.后来在Android出1.5版本之后,我第一时间下载了eclipse开发工 ...
- 通过LDF文件实现日志回滚将数据恢复(转)
该方法数据库恢复(www.db-recovery.com)思路 1. 创建数据TEST 2. 创建表TEMP_01 3. 在表TEMP_01中插入100条数据 4. 备份现有的数据库 5. 再次向表T ...
- SerializableMaplist传递数据
package com.xjx.data; import java.io.Serializable; import java.util.List; import java.util.Map; /** ...
- 关于静态库和动态库的理解(C++)
库的存在,是软件模块化的基础. 库存在的意义: } 库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议. } 现实中每个程序都要依赖很多基础的底层库,不可能每个人的 ...
- NOSQL之【Redis学习:配置说明】
# yes:后台运行:no:不是后台运行(老版本默认) daemonize yes # redis的进程文件 pidfile /var/run/redis.pid # 端口 port # bind_a ...
- php class类的用法详细总结
以下是对php中class类的用法进行了详细的总结介绍,需要的朋友可以过来参考下 一:结构和调用(实例化): class className{} ,调用:$obj = new className(); ...
- ecshop会员中心增加订单搜索功能
在user.php中的act=order_list中增加以下程序. $order_sn = isset($_REQUEST['order_sn'])?$_REQUEST['order_sn']:''; ...