1.题面
http://poj.org/problem?id=2104
2.题意
给定一个序列a,求a[l----r]之间的第k大值
3.思路
听说要用主席树做,我暂时还不会,用zkw线段树写了一个,然后普通线段树过了,zkw线段树tle了,更确切地说是POJ没法过,其他OJ如SPOJ上过了,那样的话,思路应该没有问题了
新补了一个主席树的做法
4.代码
zkw线段树
/*****************************************************************
> File Name: Cpp_Acm.cpp
> Author: Uncle_Sugar
> Mail: uncle_sugar@qq.com
> Created Time: 2016年07月18日 星期一 21时59分32秒
*****************************************************************/
# include <cstdio>
# include <vector>
# include <algorithm>
using namespace std;
const int size = 300000 + 10;
int n,m;
vector<int> T[2*size];
int sz;
void Build(int n){
for (sz=1;sz<n+2;sz<<=1);
int i = 0;
for (i=sz+1;i<=sz+n;i++){
T[i].clear();
int tmp;
scanf("%d",&tmp);
T[i].push_back(tmp);
}
for (i=sz-1;i>=1;i--){
T[i].resize(T[i<<1].size()+T[i<<1|1].size());
merge(T[i<<1].begin(),T[i<<1].end(),T[i<<1|1].begin(),T[i<<1|1].end(),T[i].begin());
}
}
int Query(int s,int t,int x){
int ret = 0;
for (s=s+sz-1,t=t+sz+1;s^t^1;s>>=1,t>>=1){
if (~s&1) ret += upper_bound(T[s^1].begin(),T[s^1].end(),x) - T[s^1].begin();
if (t&1) ret += upper_bound(T[t^1].begin(),T[t^1].end(),x) - T[t^1].begin();
}
return ret;
}
int main()
{
int i,j;
while (~scanf("%d%d",&n,&m)){
Build(n);
while (m--){
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
int lb = 0,rb = n-1,mid;
while (lb < rb){
mid = lb+rb>>1;
int x = Query(l,r,T[1][mid]);
if (x<k) lb = mid + 1;
else rb = mid;
}
printf("%d\n",T[1][rb]);
}
}
return 0;
}
主席树
# include <cstdio>
# include <cstring>
# include <cctype>
# include <cmath>
# include <cstdlib>
# include <climits>
# include <iostream>
# include <iomanip>
# include <set>
# include <map>
# include <vector>
# include <stack>
# include <queue>
# include <algorithm>
using namespace std;
const int debug = 1;
const int size = 3000000 + 10;
const int INF = INT_MAX>>1;
typedef long long ll;
int lson[size],rson[size];
int data[size];
int tot = 0;
int T[size];
int n,m;
int num[size],h[size];
int sz;
void init(){
for (int i=1;i<=n;i++)
h[i] = num[i];
sort(h+1,h+n+1);
sz = unique(h+1,h+n+1) - h - 1;
tot = 0;
}
int hash(int x){return lower_bound(h+1,h+sz+1,x) - h;}
int Build(int l,int r){
int root = tot++;
data[root] = 0;
if (l < r){
int mid = l+r>>1;
lson[root] = Build(l,mid);
rson[root] = Build(mid+1,r);
}
return root;
}
int update(int root,int pos,int val){
int newroot = tot++;
int ret = newroot;
data[newroot] = data[root] + val;
int l = 1,r = sz;
while (l<r){
int mid = l+r>>1;
if (pos <= mid){
lson[newroot] = tot++;rson[newroot] = rson[root];
newroot = lson[newroot];root = lson[root];
r = mid;
}else {
lson[newroot] = lson[root];rson[newroot] = tot++;
newroot = rson[newroot];root = rson[root];
l = mid+1;
}
data[newroot] = data[root] + val;
}
return ret;
}
int Query(int lt,int rt,int k){
int lb = 1,rb = sz,mid;
while (lb < rb){
mid = lb+rb>>1;
if (data[lson[rt]] - data[lson[lt]] >= k){
lt = lson[lt];rt = lson[rt];
rb = mid;
}else {
k -= data[lson[rt]] - data[lson[lt]];
lt = rson[lt];rt = rson[rt];
lb = mid + 1;
}
}
return lb;
}
int main(){
std::ios::sync_with_stdio(false);cin.tie(0);
int i,j;
while (cin >> n >> m){
for (i=1;i<=n;i++) cin >> num[i];
init();
T[0] = Build(1,sz);
for (i=1;i<=n;i++){
int pos = hash(num[i]);
T[i] = update(T[i-1],pos,1);
}
while (m--){
int l,r,k;
cin >> l >> r >> k;
cout << h[Query(T[l-1],T[r],k)] << endl;
}
}
return 0;
}