题意就是区间第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小的更多相关文章

  1. POJ2104 K-th Number —— 区间第k小 整体二分

    题目链接:https://vjudge.net/problem/POJ-2104 K-th Number Time Limit: 20000MS   Memory Limit: 65536K Tota ...

  2. 主席树总结(经典区间第k小问题)(主席树,线段树)

    接着上一篇总结--可持久化线段树来整理吧.点击进入 这两种数据结构确实有异曲同工之妙.结构是很相似的,但维护的主要内容并不相同,主席树的离散化.前缀和等思想也要更难理解一些. 闲话 话说刚学习主席树的 ...

  3. ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解

    题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...

  4. 【XSY2720】区间第k小 整体二分 可持久化线段树

    题目描述 给你你个序列,每次求区间第\(k\)小的数. 本题中,如果一个数在询问区间中出现了超过\(w\)次,那么就把这个数视为\(n\). 强制在线. \(n\leq 100000,a_i<n ...

  5. A - 低阶入门膜法 - K-th Number (主席树查询区间第k小)

    题目链接:https://cn.vjudge.net/contest/284294#problem/A 题目大意:主席树查询区间第k小. 具体思路:主席树入门. AC代码: #include<i ...

  6. HDU 2665.Kth number 区间第K小

    Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. POJ 2014.K-th Number 区间第k小 (归并树)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 57543   Accepted: 19893 Ca ...

  8. Dynamic Rankings || 动态/静态区间第k小(主席树)

    JYF大佬说,一星期要写很多篇博客才会有人看 但是我做题没有那么快啊QwQ Part1 写在前面 区间第K小问题一直是主席树经典题=w=今天的重点是动态区间第K小问题.静态问题要求查询一个区间内的第k ...

  9. 少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小

    少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小 有一道题(BZOJ 1901)是这样的:n个数,m个询问,询问有两种:修改某个数/询问区间第k小. 不带修改的区间第k小用主席树很好写 ...

随机推荐

  1. php 二维转一维

    Array(    [0] => Array        (            [salesorderid] => 10001            [createdtime] =& ...

  2. wamp下开启SSL,解决APACHE启动问题

    wamp开启SSL解决wamp5_1.7.4中APACHE启动问题 1.#修改httpd.conf文件LoadModule ssl_module modules/mod_ssl.soInclude c ...

  3. Ajax请求过程中显示“进度”的简单实现

    Ajax在Web应用中使用得越来越频繁.在进行Ajax调用过程中一般都具有这样的做法:显示一个GIF图片动画表明后台正在工作,同时阻止用户操作本页面(比如Ajax请求通过某个按钮触发,用户不能频繁点击 ...

  4. MySQL基础学习之触发器

    查看触发器 SHOW TRIGGER\G 创建触发器 CREATE TRIGGER 触发器名字 BEFORE/AFTER DELETE ON 表名 FOR EACH ROW INSERT INTO 表 ...

  5. 最完美解决Nginx部署ThinkPHP项目的办法

    网上通用解决方法的配置如下: server { ... location / { index index.htm index.html index.php; #访问路径的文件不存在则重写URL转交给T ...

  6. ECshop网点程序优化-自动生成类目页Keywords、Desciption Meta

    ECshop支持针对每个新建的类目自定义Keywords.Description Meta信息,好处就不用说了,帮助SEO或者让浏览者了解这是什么页面,但如果有几百个类目的时候,人工去写这些类目又有点 ...

  7. Xilium.CefGlue利用XHR实现Js调用c#方法

    防外链 博客园原文地址在这里http://www.cnblogs.com/shen6041/p/3442499.html 引 Xilium CefGlue是个不错的cef扩展工程,托管地址在这里 ht ...

  8. SQL的多表操作

    多表更新: 假定我们有两张表,一张表为Product表存放产品信息,其中有产品价格列Price:另外一张表是ProductPrice表,我们要将ProductPrice表中的价格字段Price更新为P ...

  9. SLua

    安装 1.下载最新版,将Assets目录里的所有内容复制到工程中,对于最终产品,可以删除例子,文档等内容,如果是开发阶段则无所谓. 2.等待unity编译完毕,如果一切顺利的话,将出现SLua菜单,点 ...

  10. Spring AOP 性能监控器

    spring,真是一个好东西:性能,真是个让人头疼又不得不面对的问题.如何排查出项目中性能瓶颈?如何迅速定位系统的慢查询?在这我就不说spring自带的性能监控器了,实在是有些简陋.下面就说说我自己写 ...