【POJ2104】K-th Number(主席树)
题意:有n个数组成的序列,要求维护数据结构支持在线的下列两种操作:
1:单点修改,将第x个数修改成y
2:区间查询,询问从第x个数到第y个之间第K大的数
n<=100000,a[i]<=10^9
思路:一年前写过的第一道主席树,现在有了更深的理解
最朴素的想法是设t[i,j]为i时刻[1..j]的个数之和
询问时区间(x,y)时只需取出t[y]-t[x-1]这棵线段树,在其中二分查找即可
那么问题来了:这样的写法空间复杂度是O(n2)级别的,且每次更改只有logn个点会被更改
有很多一模一样的线段树中的节点是重复的,如何利用它们
充分利用历史版本,使用类似链表的方法将它们链接
比如只有左儿子被修改的节点就只新开左儿子,右儿子链到上一个时刻的右儿子即可
单点修改的时间和空间复杂度都是O(NlogN)
var t:array[..]of record
l,r,s:longint;
end;
a,b,c,d,root:array[..]of longint;
n,m,i,x,y,k,cnt:longint; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; procedure qsort(l,r:longint);
var i,j,mid:longint;
begin
i:=l; j:=r; mid:=a[(l+r)>>];
repeat
while mid>a[i] do inc(i);
while mid<a[j] do dec(j);
if i<=j then
begin
swap(a[i],a[j]);
swap(c[i],c[j]);
inc(i); dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end; procedure update(l,r:longint;var p:longint;x:longint);
var mid:longint;
begin
inc(cnt);
t[cnt]:=t[p];
p:=cnt;
inc(t[p].s);
if l=r then exit;
mid:=(l+r)>>;
if x<=mid then update(l,mid,t[p].l,x)
else update(mid+,r,t[p].r,x);
end; function query(p1,p2,l,r,k:longint):longint;
var mid,tmp:longint;
begin
if l=r then exit(l);
tmp:=t[t[p2].l].s-t[t[p1].l].s;
mid:=(l+r)>>;
if tmp>=k then exit(query(t[p1].l,t[p2].l,l,mid,k))
else exit(query(t[p1].r,t[p2].r,mid+,r,k-tmp));
end; begin
assign(input,'poj2104.in'); reset(input);
assign(output,'poj2104.out'); rewrite(output);
readln(n,m);
for i:= to n do
begin
read(a[i]); b[i]:=a[i]; c[i]:=i;
end;
qsort(,n);
d[c[]]:=;
for i:= to n do
if a[i]<>a[i-] then d[c[i]]:=d[c[i-]]+
else d[c[i]]:=d[c[i-]];
for i:= to n do
begin
root[i]:=root[i-];
update(,n,root[i],d[i]);
end;
for i:= to m do
begin
readln(x,y,k);
writeln(a[query(root[x-],root[y],,n,k)]);
end;
close(input);
close(output);
end.
UPD(2018.9.19):C++
//无修改区间第K小值
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef vector<int> VI;
#define fi first
#define se second
#define MP make_pair
#define N 210000
#define MOD 1000000007
#define eps 1e-8
#define pi acos(-1)
#define oo 1e9 struct arr
{
int l,r,s;
}t[];
int a[N],b[N],c[N],root[N],cnt,n; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} int Discrete(int x)
{
int l=;
int r=n;
while(l<=r)
{
int mid=(l+r)>>;
if(b[mid]==x) return c[mid];
if(b[mid]<x) l=mid+;
else r=mid-;
}
} void update(int l,int r,int x,int &p)
{
t[++cnt].l=t[p].l;
t[cnt].r=t[p].r;
t[cnt].s=t[p].s;
p=cnt;
t[p].s++;
if(l==r) return;
int mid=(l+r)>>;
if(x<=mid) update(l,mid,x,t[p].l);
else update(mid+,r,x,t[p].r);
} int query(int p1,int p2,int l,int r,int k)
{
if(l==r) return l;
int tmp=t[t[p2].l].s-t[t[p1].l].s;
int mid=(l+r)>>;
if(tmp>=k) return query(t[p1].l,t[p2].l,l,mid,k);
else return query(t[p1].r,t[p2].r,mid+,r,k-tmp);
} int main()
{
//freopen("poj2104.in","r",stdin);
//freopen("poj2104.out","w",stdout);
int m;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
for(int i=;i<=n;i++) b[i]=a[i];
sort(b+,b+n+);
c[]=;
for(int i=;i<=n;i++)
{
c[i]=c[i-];
if(b[i]!=b[i-]) c[i]++;
}
for(int i=;i<=n;i++) a[i]=Discrete(a[i]); //离散化
for(int i=;i<=n;i++)
{
root[i]=root[i-];
update(,n,a[i],root[i]);
}
for(int i=;i<=m;i++)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
int ans=b[query(root[x-],root[y],,n,k)];
printf("%d\n",ans);
} return ;
}
【POJ2104】K-th Number(主席树)的更多相关文章
- 【poj2104】K-th Number 主席树
题目描述 You are working for Macrohard company in data structures department. After failing your previou ...
- poj2104 k-th number 主席树入门讲解
poj2104 k-th number 主席树入门讲解 定义:主席树是一种可持久化的线段树 又叫函数式线段树 刚开始学是不是觉得很蒙逼啊 其实我也是 主席树说简单了 就是 保留你每一步操作完成之后 ...
- poj 2104 K-th Number 主席树+超级详细解释
poj 2104 K-th Number 主席树+超级详细解释 传送门:K-th Number 题目大意:给出一段数列,让你求[L,R]区间内第几大的数字! 在这里先介绍一下主席树! 如果想了解什么是 ...
- [POJ2104] K – th Number (可持久化线段树 主席树)
题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输 ...
- poj2104 K-th Number区间第k小值 主席树
原来主席树就是可持久化线段树啊,刚知道,,, 作为一道裸题,还是必A的,然而一开始偷懒不写离散化跪了N多遍,后来在缪大的帮助下发现了这个问题,遂A之 ——又是这种破问题,实在不想说自己了 把n个数看成 ...
- 【POJ2104】【HDU2665】K-th Number 主席树
[POJ2104][HDU2665]K-th Number Description You are working for Macrohard company in data structures d ...
- POJ2104 K-th Number[主席树]【学习笔记】
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 51440 Accepted: 17594 Ca ...
- [poj2104] K-th Number (主席树)
主席树 Description You are working for Macrohard company in data structures department. After failing y ...
- 主席树:POJ2104 K-th Number (主席树模板题)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 44952 Accepted: 14951 Ca ...
- POJ 2104 K-th Number 主席树(区间第k大)
题目链接: http://poj.org/problem?id=2104 K-th Number Time Limit: 20000MSMemory Limit: 65536K 问题描述 You ar ...
随机推荐
- 在无TNS配置时,登录到数据库。
sqlplus user/pw@ip:port/servicename sqlplus user/pwd@tnsname sqlplus user/pwd---aix sqlplus /nolog&g ...
- unity3d sqlite数据库的读写方法
首先,我们要从unity的安装路径中复制mono.data.sqlite.dll和sqlite3.dll两个动态链接库到untiy的plugins目录下,如下图所示: 使用navicat for sq ...
- OC和C++的混用2
苹果的Objective-C编译器允许用户在同一个源文件里自由地混合使用C++和Objective-C,混编后的语言叫Objective-C++.有了它,你就可以在Objective-C应用程序中使用 ...
- 如何解决U盘装系统后磁盘总容量变小?
我在用Win32_Disk_Imager工具制作U盘系统盘之后,发现U盘大小变为2M,另外的大小没有被分配,解决办法如下. 打开:http://jingyan.baidu.com/article/59 ...
- C++ Primer读书笔记(一)第一篇:C++概述,第一章:开始
1. 主要内容 介绍程序语言的核心思想和C++的基本概念. 印象比较深刻的就是分而治之(divide and conque)的分解思想. 2. 知识广场 1) C++ 文件后缀 cc, cpp,,cx ...
- 为PHPcms扩展json采集
最近想用phpcms做个新闻类网站,做采集的时候发现没有json的选项,于是自己动手,增加了采集json选项. 由于有的网站并不是纯json传输,而是jsonp,因此我把json,jsonp数据都当做 ...
- makedown语法
文章转载至:https://blog.csdn.net/u014061630/article/details/81359144#1-%E5%BF%AB%E6%8D%B7%E9%94%AE 前言 写过博 ...
- 二叉排序树:POJ2418-Hardwood Species(外加字符串处理)
Hardwood Species Time Limit: 10000MS Memory Limit: 65536K Description Hardwoods are the botanical gr ...
- ACM训练联盟周赛 A. Teemo's bad day
65536K Today is a bad day. Teemo is scolded badly by his teacher because he didn't do his homework ...
- 函数名&函数名取地址
有时看到如下的代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /*****************************/ #includ ...