Problem Description
Give you a sequence and ask you the kth big number of a inteval.
Input
The first line is the number of the test cases.
For each test case, the first line contain two integer n and m (n, m <= 100000), indicates the number of integers in the sequence and the number of the quaere.
The second line contains n integers, describe the sequence.
Each of following m lines contains three integers s, t, k.
[s, t] indicates the interval and k indicates the kth big number in interval [s, t]
For each test case, the first line contain two integer n and m (n, m <= 100000), indicates the number of integers in the sequence and the number of the quaere.
The second line contains n integers, describe the sequence.
Each of following m lines contains three integers s, t, k.
[s, t] indicates the interval and k indicates the kth big number in interval [s, t]
Output
For each test case, output m lines. Each line contains the kth big number.
Sample Input
1 10 1 1 4 2 3 5 6 7 8 9 0 1 3 2
Sample Output
2
这是一道求区间第K大的划分树模板题
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
const int N = 100010;
int sum[20][N],tr[20][N],sr[N];
void build(int l, int r, int d)
{
if(l == r) return;
int mid = l + r >> 1, i, lp = l, rp = mid+1;
int eqnum, tp=0;
for(int i=l; i<=r; i++) if(tr[d][i] < sr[mid]) tp++;
eqnum = mid-l+1-tp;
tp = 0;
for(i=l; i<=r; i++)
{
sum[d][i] = sum[d][i-1];
if(tr[d][i] < sr[mid])
tr[d+1][lp++] = tr[d][i], sum[d][i]++;
else if(tr[d][i] == sr[mid] && tp < eqnum)
tr[d+1][lp++] = tr[d][i], sum[d][i]++, tp++;
else tr[d+1][rp++] = tr[d][i];
}
build(l,mid,d+1);
build(mid+1,r,d+1);
}
int query(int s, int t, int k, int l, int r, int d)
{
//
if(s == t) return tr[d][s];
int mid = l + r >> 1;
int x = sum[d][s-1] - sum[d][l-1];
int y = sum[d][t] - sum[d][s-1];
if(y >= k)
return query(l+x, l+x+y-1,k, l, mid, d+1);
return query(s-l-x+mid+1, mid + s-l-x + t-s+1-y, k-y, mid+1, r, d+1);
}
int main()
{
int i,j,k,m,n;
int a,b,c;
int tt;
scanf("%d",&tt);
while(tt--)
{
scanf("%d%d",&n,&m);
for(i=1; i<=n; i++) scanf("%d",sr+i);
for(i=1; i<=n; i++) tr[0][i] = sr[i];
sort(sr+1,sr+1+n);
build(1,n,0);
while(m--)
{
scanf("%d %d %d",&a,&b,&c);
printf("%d\n",query(a,b,c,1,n,0));
}
}
return 0;
}
/**********
主席树版
**********/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 100010;
const int M = MAXN * 30;
int n,q,m,tot;
int a[MAXN], t[MAXN];
int T[M], lson[M], rson[M], c[M];
void Init_hash()
{
for(int i = 1; i <= n;i++)
t[i] = a[i];
sort(t+1,t+1+n);
m = unique(t+1,t+1+n)-t-1;
}
int build(int l,int r)
{
int root = tot++;
c[root] = 0;
if(l != r)
{
int mid = (l+r)>>1;
lson[root] = build(l,mid);
rson[root] = build(mid+1,r);
}
return root;
}
int Hash(int x)
{
return lower_bound(t+1,t+1+m,x) - t;
}
int update(int root,int pos,int val)
{
int newroot = tot++, tmp = newroot;
c[newroot] = c[root] + val;
int l = 1, r = m;
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
{
rson[newroot] = tot++; lson[newroot] = lson[root];
newroot = rson[newroot]; root = rson[root];
l = mid+1;
}
c[newroot] = c[root] + val;
}
return tmp;
}
int query(int left_root,int right_root,int k)
{
int l = 1, r = m;
while( l < r)
{
int mid = (l+r)>>1;
if(c[lson[left_root]]-c[lson[right_root]] >= k )
{
r = mid;
left_root = lson[left_root];
right_root = lson[right_root];
}
else
{
l = mid + 1;
k -= c[lson[left_root]] - c[lson[right_root]];
left_root = rson[left_root];
right_root = rson[right_root];
}
}
return l;
}
int main()
{
int tt;
scanf("%d",&tt);
while(tt--)
{
scanf("%d%d",&n,&q);
tot = 0;
for(int i = 1;i <= n;i++)
scanf("%d",&a[i]);
Init_hash();
T[n+1] = 0, build(1,m);
for(int i = n;i ;i--)
{
int pos = Hash(a[i]);
T[i] = update(T[i+1],pos,1);
}
while(q--)
{
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",t[query(T[l],T[r+1],k)]);
}
}
return 0;
}