题意:有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(主席树)的更多相关文章

  1. 【poj2104】K-th Number 主席树

    题目描述 You are working for Macrohard company in data structures department. After failing your previou ...

  2. poj2104 k-th number 主席树入门讲解

    poj2104 k-th number 主席树入门讲解 定义:主席树是一种可持久化的线段树 又叫函数式线段树   刚开始学是不是觉得很蒙逼啊 其实我也是 主席树说简单了 就是 保留你每一步操作完成之后 ...

  3. poj 2104 K-th Number 主席树+超级详细解释

    poj 2104 K-th Number 主席树+超级详细解释 传送门:K-th Number 题目大意:给出一段数列,让你求[L,R]区间内第几大的数字! 在这里先介绍一下主席树! 如果想了解什么是 ...

  4. [POJ2104] K – th Number (可持久化线段树 主席树)

    题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输 ...

  5. poj2104 K-th Number区间第k小值 主席树

    原来主席树就是可持久化线段树啊,刚知道,,, 作为一道裸题,还是必A的,然而一开始偷懒不写离散化跪了N多遍,后来在缪大的帮助下发现了这个问题,遂A之 ——又是这种破问题,实在不想说自己了 把n个数看成 ...

  6. 【POJ2104】【HDU2665】K-th Number 主席树

    [POJ2104][HDU2665]K-th Number Description You are working for Macrohard company in data structures d ...

  7. POJ2104 K-th Number[主席树]【学习笔记】

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

  8. [poj2104] K-th Number (主席树)

    主席树 Description You are working for Macrohard company in data structures department. After failing y ...

  9. 主席树:POJ2104 K-th Number (主席树模板题)

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

  10. POJ 2104 K-th Number 主席树(区间第k大)

    题目链接: http://poj.org/problem?id=2104 K-th Number Time Limit: 20000MSMemory Limit: 65536K 问题描述 You ar ...

随机推荐

  1. ssh整合思想 Spring与Hibernate的整合ssh整合相关JAR包下载 .MySQLDialect方言解决无法服务器启动自动update创建表问题

    除之前的Spring相关包,还有structs2包外,还需要Hibernate的相关包 首先,Spring整合其他持久化层框架的JAR包 spring-orm-4.2.4.RELEASE.jar  ( ...

  2. Spring中使用事务搭建转账环境 转账操作,

    演示不使用事务出现异常情况 Dao层两个方法lessMoney()和moreMoney() package com.swift; import org.springframework.jdbc.cor ...

  3. DeepFaceLab: SSE,AVX, OpenCL 等版本说明!

    Deep Fake Lab早期只有两个版本,一个是专门正对NVIDIA显卡的CUDA9的版本,另一个是支持CPU的版本. 三月初该项目作者对tenserFlow,Cuda的版本进行了升级,预编译的软件 ...

  4. Python学习笔记:open函数和with临时运行环境(文件操作)

    open函数 1.open函数: file=open(filename, encoding='utf-8'),open()函数是Python内置的用于对文件的读写操作,返回的是文件的流对象(而不是文件 ...

  5. Python学习笔记:字符串

    字符串 字符串定义:字符串可以使用一对单引号.双引号或三引号来定义,即便是单个字符也会当做字符串来处理(Python中没有字符类型,单个字符也就是只有一个字符的字符串而已). 原始字符串:字符串中反斜 ...

  6. Altium Designer入门学习笔记1.软件安装与资料收集

    一.软件安装 微信:http://url.cn/5Eudzt9 关注微信公众号"软件安装管家",点击"软件目录",弹出"软件目录",点击进入 ...

  7. Android内核编译步骤

    android_4.0.4_tq210$ source build/envsetup.shandroid_4.0.4_tq210$ lunch 5/android_4.0.4_tq210$ make ...

  8. Linux学习-SRPM 的使用 : rpmbuild (Optional)

    新版的 rpm 已经 将 RPM 与 SRPM 的指令分开了,SRPM 使用的是 rpmbuild 这个指令,而不是 rpm 喔! 利用默认值安装 SRPM 文件 (--rebuid/--recomp ...

  9. HDU 3315 KM My Brute

    参考题解 二分图的最优匹配.图很容易建立.再处理相似度的时候.把每个权值扩大100倍.然后再对i==j时 特殊标记.使他们的权值再++1.后面选择的时候就很容易挑出.按原匹配 匹配的个数. 100*( ...

  10. String的getBytes()方法

    这是一篇转帖: 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/maxracer/archive/2010/12/14/6075057.aspx 在Java中,Stri ...