您的位置:首页 > 其它

主席树模板求不带修改的区间k大

2016-07-06 08:14 330 查看
现在会主席树是不是晚了点。主席树的牛逼就是公用了节点然后因为类似前缀和(其实可以叫做时间前缀和)所以节点可以拿来相减。然后就十分玄妙了。。。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = (int)3e6 + 10;
const int maxn = (int)1e5;
int lson
, rson
, sum
;
int Time
, total;
int s
, X
;
void PushUp(int rt){
sum[rt] = sum[lson[rt]] + sum[rson[rt]];
}
int build(int L, int R){
int now = ++total;
if (L == R){
lson[now] = rson[now] = 0;
sum[now] = 0;
return now;
}
int m = (L + R) >> 1;
lson[now] = build(L, m);
rson[now] = build(m + 1, R);
PushUp(now);
return now;
}
int update(int rt, int pos, int L, int R){
int now = ++total;
if (L == R){
sum[now] = sum[rt] + 1;
lson[now] = rson[now] = 0;
return now;
}
int m = (L + R) >> 1;
if (pos <= m){
lson[now] = update(lson[rt], pos, L, m);
rson[now] = rson[rt];
}else{
rson[now] = update(rson[rt], pos, m+ 1, R);
lson[now] = lson[rt];
}
PushUp(now);
return now;
}
int ask(int rt1, int rt2, int k, int L, int R){
if (L == R) return X[L];
int number = sum[lson[rt2]] - sum[lson[rt1]];
int m = (L + R) >> 1;
if (number >= k)
return ask(lson[rt1], lson[rt2], k, L, m);
else
return ask(rson[rt1], rson[rt2], k - number, m +1, R);
}
int main(){
int cs; scanf("%d", &cs);
int n, m;
while(cs--){
scanf("%d%d", &n, &m);
int cnt = 0;
for (int i = 1; i <= n; i++){
scanf("%d", &s[i]);
X[++cnt] = s[i];
}
sort(X + 1, X + 1 + cnt);
int all = 1;
for (int i = 2; i <= cnt; i++)
if (X[i] != X[i - 1]) X[++all] = X[i];
total = 0;
Time[0] = build(1, all);
for (int i = 1; i <= n; i++){
int pos = lower_bound(X + 1, X + 1 + all, s[i]) - X;
Time[i] = update(Time[i - 1], pos, 1, all);
}
while(m--){
int L, R, k;
scanf("%d%d%d", &L, &R, &k);
printf("%d\n", ask(Time[L - 1], Time[R], k, 1, all));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: