Description
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询
k
在区间内的排名
2.查询区间内排名为
3.修改某一位值上的数值
4.查询
k
在区间内的前驱(前驱定义为小于
5.查询
k
在区间内的后继(后继定义为大于
Input
第一行两个数
n,m
表示长度为
n
的有序序列和
第二行有
n
个数,表示有序序列
下面有
若
opt=1
则为操作
1
,之后有三个数
若
opt=2
则为操作
2
,之后有三个数
若
若
若
很显然的树套树。。。。
我是线段树套
但不知道为什么
Linux
下一直RE啊QAQ
从
BZOJ
管理员那里要来的数据
windows
下测都能过的QAQ
#include <cstdio>
#include <cstdlib>
inline int Max(int a, int b) {
return a > b ? a : b;
}
inline int Min(int a, int b) {
return a < b ? a : b;
}
inline char get(void) {
static char buf[1000000], *p1 = buf, *p2 = buf;
if (p1 == p2) {
p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin);
if (p1 == p2) return EOF;
}
return *p1++;
}
inline void read(int &x) {
x = 0; char c = get(); int sign = 1;
for (; c < '0' || c > '9'; c = get()) if(c == '-') sign = 0;
for (; c >= '0' && c <= '9'; x = (x << 1) + (x << 3) + c - '0', c = get());
x = sign ? x : -x;
}
const int N = 50010, INF = 1 << 30;
struct node {
node *ch[2];
int key, pri, size, num;
inline void maintain(void) {
size = ch[0]->size + ch[1]->size + num;
}
inline int cmp(int x) {
return x == key ? -1 : x > key;
}
inline int cmpk(int k) {
int d = k - ch[0]->size;
return d == 1 ? -1 : d > 1;
}
};
node mem[N << 6];
node *Tail, *null, *t;
void Init(void) {
Tail = mem; null = Tail++;
null->ch[0] = null->ch[1] = null;
null->size = null->key = null->pri = null->num = 0;
}
inline node* NewNode(int key) {
node* p = Tail++; p->key = key;
p->size = 1; p->pri = rand();
p->ch[0] = p->ch[1] = null; p->num = 1;
}
struct Treap {
private:
node *rt;
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) {
int d = o->cmp(x);
if (d == -1) {
o->num++; o->size++; return;
}
if (o->ch[d] == null) {
o->ch[d] = NewNode(x);
if (o->ch[d]->pri > o->pri) Rotate(o, d ^ 1);
o->maintain();
return;
}
Insert(o->ch[d], x);
if (o->ch[d]->pri > o->pri) Rotate(o, d ^ 1);
o->maintain();
}
void Remove(node* &o, int x) {
int d = o->cmp(x);
if (d == -1) {
if (o->num == 1) {
if (o->ch[0] != null && o->ch[1] != null) {
int d2 = o->ch[0]->pri > o->ch[1]->pri;
Rotate(o, d2); Remove(o->ch[d2], x);
} else {
if (o->ch[0] != null) o = o->ch[0];
else if (o->ch[1] != null) o = o->ch[1];
else o = null;
}
} else {
o->num--; o->size--;
}
} else {
Remove(o->ch[d], x);
}
if (o != null) o->maintain();
}
int Pre(node* o, int x) {
if (o == null) return 0;
if (o->key < x) return Max(Pre(o->ch[1], x), o->key);
else return Pre(o->ch[0], x);
}
int Suc(node* o, int x) {
if (o == null) return INF;
if (o->key > x) return Min(Suc(o->ch[0], x), o->key);
else return Suc(o->ch[1], x);
}
int GetRank(node* o, int x) {
if (o == null) return 0;
int d = o->cmp(x);
if (d == -1) return o->ch[0]->size;
if (d) return GetRank(o->ch[1], x) + o->ch[0]->size + o->num;
else return GetRank(o->ch[0], x);
}
public:
inline void Insert(int x) {
if (rt == NULL) rt = NewNode(x);
else Insert(rt, x);
}
inline void Modify(int x, int y) {
Remove(rt, x); Insert(rt, y);
}
inline int Rank(int x) {
return GetRank(rt, x);
}
inline int Pre(int x) {
return Pre(rt, x);
}
inline int Suc(int x) {
return Suc(rt, x);
}
};
Treap T[N << 5];
int a[N];
int n, m, x, y, z, opt, res, cnt;
void Build(int o, int l, int r) {
for (int i = l; i <= r; i++) T[o].Insert(a[i]);
if (l == r) return;
int mid = (l + r) >> 1;
Build(o << 1, l, mid);
Build(o << 1 | 1, mid + 1, r);
}
int Rank(int o, int l, int r, int L, int R, int x) {
if (l >= L && r <= R) return T[o].Rank(x);
int mid = (l + r) >> 1, res = 0;
if (L <= mid) res += Rank(o << 1, l, mid, L, R, x);
if (R > mid) res += Rank(o << 1 | 1, mid + 1, r, L, R, x);
return res;
}
int Kth(int L, int R, int k) {
int l = 1, r = INF, mid, pos;
while (l <= r) {
mid = (l + r) >> 1;
if (Rank(1, 1, n, L, R, mid) + 1 <= k) {
pos = mid; l = mid + 1;
} else {
r = mid - 1;
}
}
return pos;
}
void Modify(int o, int l, int r, int pos, int x) {
T[o].Modify(a[pos], x);
if (l == r) return;
int mid = (l + r) >> 1;
if (pos <= mid) Modify(o << 1, l, mid, pos, x);
else Modify(o << 1 | 1, mid + 1, r, pos, x);
}
int Pre(int o, int l, int r, int L, int R, int x) {
if (l >= L && r <= R) return T[o].Pre(x);
int mid = (l + r) >> 1, res = 0;
if (L <= mid) res = Max(Pre(o << 1, l, mid, L, R, x), res);
if (R > mid) res = Max(Pre(o << 1 | 1, mid + 1, r, L, R, x), res);
return res;
}
int Suc(int o, int l, int r, int L, int R, int x) {
if (l >= L && r <= R) return T[o].Suc(x);
int mid = (l + r) >> 1, res = INF;
if (L <= mid) res = Min(Suc(o << 1, l, mid, L, R, x), res);
if (R > mid) res = Min(Suc(o << 1 | 1, mid + 1, r, L, R, x), res);
return res;
}
int main(void) {
read(n); read(m); Init();
for (int i = 1; i <= n; i++) read(a[i]);
Build(1, 1, n); t = null;
for (int i = 0; i < m; i++) {
read(opt); read(x); read(y);
if (opt == 1) {
read(z); printf("%d\n", Rank(1, 1, n, x, y, z) + 1);
} else if (opt == 2) {
read(z); printf("%d\n", Kth(x, y, z));
} else if (opt == 3) {
Modify(1, 1, n, x, y); a[x] = y;
} else if (opt == 4) {
read(z); printf("%d\n", Pre(1, 1, n, x, y, z));
} else {
read(z); printf("%d\n", Suc(1, 1, n, x, y, z));
}
}
return 0;
}