一、查询整体区间第K大 && 序列中比 x 小的数的个数
例题:spoj3273.ORDERSET——初始一个空序列,支持插入、删除一个数,查询整个序列中的第K大和整个序列中小于x的数的个数。
难度:**
这是Treap的模版题,操作也都是基本操作,不错的一道模版题,但是spoj实在太慢了...写不好会莫名TLE
#include <cstdio>
#include <cstring>
#include <algorithm>
#define inf 1500000000
using namespace std;
typedef long long LL;
const int N = 300005;
struct treap
{
int ch[2], val, sz; unsigned int wt;
void Set(int vl) { val = vl, wt = rand() * rand() * rand(), sz = 1; }
} t[N];
int rt, n, tz, q;
void update(int x)
{
t[x].sz = t[t[x].ch[0]].sz + t[t[x].ch[1]].sz + 1;
}
void rot(int &x, bool ty)
{
int y = t[x].ch[ty]; t[x].ch[ty] = t[y].ch[!ty], t[y].ch[!ty] = x;
update(x), update(y), x = y;
}
void add(int &x, int val)
{
if (!x) { t[x = ++ tz].Set(val); return ; }
if (t[x].val == val) return ;
bool ty = val > t[x].val;
add (t[x].ch[ty], val);
(t[t[x].ch[ty]].wt > t[x].wt) ? rot(x, ty) : update(x);
}
void del(int &x, int val)
{
if (!x) return ;
if (t[x].val == val) {
bool ty = t[t[x].ch[1]].wt > t[t[x].ch[0]].wt;
if (!t[x].ch[ty]) { x = 0; return ; }
rot(x, ty), del(t[x].ch[!ty], val);
} else del(t[x].ch[val > t[x].val], val);
update(x);
}
int kth(int k)
{
int x = rt;
if (t[x].sz < k) return inf;
for (; k != t[t[x].ch[0]].sz + 1;) (k <= t[t[x].ch[0]].sz) ? x = t[x].ch[0] : (k -= t[t[x].ch[0]].sz + 1, x = t[x].ch[1]);
return t[x].val;
}
int Count(int x)
{
if (!x) return 0;
if (t[x].val < q) return Count(t[x].ch[1]) + t[t[x].ch[0]].sz + 1;
else return Count(t[x].ch[0]);
}
void init()
{
scanf("%d", &n);
}
void doit()
{
for (int i = 1; i <= n; i ++) {
int x; char ty;
scanf (" %c %d", &ty, &x);
if (ty == 'I') add(rt, x);
else if (ty == 'D') del(rt, x);
else if (ty == 'K') {
x = kth(x);
(x != inf) ? printf ("%d\n", x) : puts("invalid");
}
else q = x, printf ("%d\n", Count(rt));
}
}
int main()
{
init();
doit();
return 0;
}
二、查询一个序列中第一大于(等于)x和小于(等于)x的数
例题:poj2892——有一个1到n的序列,支持破坏一个数回复一个数,查询数x所在的没有被破坏的最长区间
难度:***
这道题用Treap维护的不是整个序列,而是被破环的数组成的序列,这个是第一次见到,应该算一种方法。这样查询的时候就可以在Treap中查找第一个大于、小于的数了。
/*
Author: JDD
PROG: poj2892.Tunnel Warfare
DATE: 2016.5.16
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_N = 100005;
int n, Q, tsz, rt, l, r;
struct Treap {
int ch[2], vl;
unsigned int wt;
void set(int _vl) {
vl = _vl; wt = rand() * rand() * rand();
}
}t[MAX_N];
void tree_rot(int &x, bool ty)
{
int y = t[x].ch[ty];
t[x].ch[ty] = t[y].ch[!ty]; t[y].ch[!ty] = x;
x = y;
}
void tree_add(int &x, int val)
{
if (!x) { t[x = ++ tsz].set(val); return; }
if (t[x].vl == val) return;
bool ty = val > t[x].vl;
tree_add(t[x].ch[ty], val);
if (t[t[x].ch[ty]].wt > t[x].wt) tree_rot(x, ty);
}
void tree_del(int &x, int val)
{
if (!x) return;
if (t[x].vl == val) {
bool ty = t[t[x].ch[1]].wt > t[t[x].ch[0]].wt;
if (!t[x].ch[ty]) { x = 0; return; }
tree_rot(x, ty); tree_del(t[x].ch[!ty], val);
} else tree_del(t[x].ch[val > t[x].vl], val);
}
void tree_find(int x, int val)
{
if (!x) return;
if (t[x].vl >= val && r >= t[x].vl) r = t[x].vl;
if (t[x].vl <= val && l <= t[x].vl) l = t[x].vl;
if (val > t[x].vl) tree_find(t[x].ch[1], val);
else if (val < t[x].vl) tree_find(t[x].ch[0], val);
}
void init()
{
scanf("%d%d", &n, &Q);
}
int st[MAX_N], top = 0;
void doit()
{
char ty; int x;
while (Q --) {
scanf(" %c ", &ty);
if (ty == 'D') {
scanf("%d", &x);
tree_add(rt, x); st[++ top] = x;
} else if (ty == 'R') {
tree_del(rt, st[top]); top --;
} else if (ty == 'Q') {
scanf("%d", &x);
l = 0, r = n + 1;
tree_find(rt, x);
if (l == x && r == x) printf("0\n");
else printf("%d\n", r - l - 1);
}
}
}
int main()
{
init();
doit();
return 0;
}