题意
给出一个序列,然后给出不同的提问。
提问就是查询在这个序列的某一个区间的第k大
思路
这题按道理来说应该是主席树的模板题,但是在网上看到其实用Treap也可以静态地处理,所以在这里就说说这种Treap的静态处理方法吧。
首先所有的区间都是互不包含的,尽管有可能会相交。
那么可以先按照顺序先排序,然后从左往右往treap中加入元素,然后查询第k大,接着到下一个区间就把多的删掉,没有的加进去。
如此反复,就可静态地求出答案
代码
代码很神奇,加上srand竟然会RE,非常迷
去掉了就AC了……
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
struct Treap {
struct Node {
Node *ch[2];
int r;
int v;
int s;
int cmp(int x) const {
if(x == v) return -1;
return x < v ? 0 : 1;
}
void maintain() {
s = 1;
if(ch[0] != NULL) {
s += ch[0] -> s;
}
if(ch[1] != NULL) {
s += ch[1] -> s;
}
}
} *root;
void init() {
root = NULL;
// srand(time(0));
}
void rotate(Node* &o, int d) {
Node* k = o -> ch[d ^ 1];
o -> ch[d ^ 1] = k -> ch[d];
k -> ch[d] = o;
o -> maintain();
k -> maintain();
o = k;
}
void insert(Node* &o, int x) {
if(o == NULL) {
o = new Node();
o -> ch[0] = o -> ch[1] = NULL;
o -> v = x;
o -> r = rand();
} else {
int d = (x v ? 0 : 1);
insert(o -> ch[d], x);
if(o -> ch[d] -> r > o -> r) {
rotate(o, d ^ 1);
}
}
o -> maintain();
}
void remove(Node* &o, int x) {
int d = o -> cmp(x);
if(d == -1) {
Node* u = o;
if(o -> ch[0] != NULL && o -> ch[1] != NULL) {
int d2 = (o -> ch[0] -> r > o -> ch[1] -> r ? 1 : 0);
rotate(o, d2);
remove(o -> ch[d2], x);
} else {
if(o -> ch[0] == NULL) {
o = o -> ch[1];
} else {
o = o -> ch[0];
}
delete u;
}
} else {
remove(o -> ch[d], x);
}
if(o != NULL) {
o -> maintain();
}
}
int find(Node* o, int x) {
while(o != NULL) {
int d = o -> cmp(x);
if(d == -1) return 1;
else o = o -> ch[d];
}
return 0;
}
int kth(Node* o, int k) {
if(o == NULL || k > o -> s || k <= 0) {
return -1;
}
int s = (o -> ch[0] == NULL ? 0 : o -> ch[0] -> s);
if(k == s + 1) {
return o -> v;
} else {
if(k <= s) {
return kth(o -> ch[0], k);
} else {
return kth(o -> ch[1], k - s - 1);
}
}
}
} treap;
const int MAXN = 100500,
MAXM = 100500;
struct question {
int l, r;
int id;
int k;
} q[MAXM];
int a[MAXN];
bool _cmp(question A, question B) {
return A.l < B.l;
}
int res[MAXM];
int main(void) {
treap.init();
int n, m;
scanf("%d%d", &n, &m);
for(int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
for(int i = 0; i < m; ++i) {
int l, r;
scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].k);
q[i].l--;
q[i].r--;
q[i].id = i;
}
sort(q, q + m, _cmp);
int l = 0, r = 0;
for(int i = 0; i < m; ++i) {
for(; l < q[i].l; ++l) {
if(l < r) {
treap.remove(treap.root, a[l]);
}
}
if(r < l) {
r = l;
}
for(; r <= q[i].r; ++r) {
treap.insert(treap.root, a[r]);
}
res[q[i].id] = treap.kth(treap.root, q[i].k);
}
for(int i = 0; i < m; ++i) {
printf("%d\n", res[i]);
}
return 0;
}