题目大意:动态维护第k小。
思路:线段树套treap,裸题,就是不怎么好写。
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 50010
#define INF 1e9
#define LEFT (pos << 1)
#define RIGHT (pos << 1|1)
#define SIZE(x) ((x == NULL) ? 0:x->size)
using namespace std;
struct Complex{
int val,cnt,size,random;
Complex *son[2];
Complex() {
son[0] = son[1] = NULL;
cnt = size = 1;
random = rand();
}
int Compare(int x) {
if(x == val) return -1;
return x > val;
}
void Maintain() {
size = cnt;
if(son[0] != NULL) size += son[0]->size;
if(son[1] != NULL) size += son[1]->size;
}
};
int cnt,asks;
int src[MAX];
char s[10];
Complex *tree[MAX << 2];
void Pretreatment();
void BuildTree(int l,int r,int pos);
int GetRank(int l,int r,int x,int y,int pos,int k);
int GetKth(int x,int y,int k);
void Modify(int l,int r,int aim,int pos,int c);
inline void Rotate(Complex *&a,bool dir);
void Insert(Complex *&a,int x);
void Delete(Complex *&a,int x);
int GetRank(Complex *a,int k);
int main()
{
Pretreatment();
cin >> cnt >> asks;
for(int i = 1;i <= cnt; ++i)
scanf("%d",&src[i]);
BuildTree(1,cnt,1);
for(int i = 1;i <= asks; ++i) {
scanf("%s",s);
int x,y,z;
if(s[0] == 'Q') {
scanf("%d%d%d",&x,&y,&z);
printf("%d\n",GetKth(x,y,z));
}
if(s[0] == 'C') {
scanf("%d%d",&x,&y);
Modify(1,cnt,x,1,y);
src[x] = y;
}
}
return 0;
}
void Pretreatment()
{
memset(tree,NULL,sizeof(tree));
}
void BuildTree(int l,int r,int pos)
{
for(int i = l;i <= r; ++i)
Insert(tree[pos],src[i]);
if(l == r) return ;
int mid = (l + r) >> 1;
BuildTree(l,mid,LEFT);
BuildTree(mid + 1,r,RIGHT);
}
int GetRank(int l,int r,int x,int y,int pos,int k)
{
if(l == x && y == r)
return GetRank(tree[pos],k);
int mid = (l + r) >> 1;
if(y <= mid) return GetRank(l,mid,x,y,LEFT,k);
if(x > mid) return GetRank(mid + 1,r,x,y,RIGHT,k);
int left = GetRank(l,mid,x,mid,LEFT,k);
int right = GetRank(mid + 1,r,mid + 1,y,RIGHT,k);
return left + right;
}
int GetKth(int x,int y,int k)
{
int L = 0,R = INF;
while(L <= R) {
int mid = (L + R) >> 1;
int temp = GetRank(1,cnt,x,y,1,mid);
if(temp < k) L = mid + 1;
else R = mid - 1;
}
return L;
}
void Modify(int l,int r,int aim,int pos,int c)
{
Delete(tree[pos],src[aim]);
Insert(tree[pos],c);
if(l == r) return ;
int mid = (l + r) >> 1;
if(aim <= mid) Modify(l,mid,aim,LEFT,c);
else Modify(mid + 1,r,aim,RIGHT,c);
}
inline void Rotate(Complex *&a,bool dir)
{
Complex *k = a->son[!dir];
a->son[!dir] = k->son[dir];
k->son[dir] = a;
a->Maintain(),k->Maintain();
a = k;
}
void Insert(Complex *&a,int x)
{
if(a == NULL) {
a = new Complex();
a->val = x;
return ;
}
int dir = a->Compare(x);
if(dir == -1)
a->cnt++;
else {
Insert(a->son[dir],x);
if(a->son[dir]->random > a->random)
Rotate(a,!dir);
}
a->Maintain();
}
void Delete(Complex *&a,int x)
{
int dir = a->Compare(x);
if(dir != -1)
Delete(a->son[dir],x);
else {
if(a->cnt > 1) a->cnt--;
else {
if(a->son[0] == NULL) a = a->son[1];
else if(a->son[1] == NULL) a = a->son[0];
else {
bool _dir = (a->son[0]->random > a->son[1]->random);
Rotate(a,_dir);
Delete(a->son[_dir],x);
}
}
}
if(a != NULL) a->Maintain();
}
int GetRank(Complex *a,int k)
{
if(a == NULL) return 0;
if(k < a->val) return GetRank(a->son[0],k);
int p = SIZE(a->son[0]) + a->cnt;
if(k > a->val) p += GetRank(a->son[1],k);
return p;
}