11057: 【原1057】无聊的LSZ
题目
题目描述
author: oldherl 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1057
Description
LSZ说:上次的作业题里面少了一道,正好就放到机考里面吧
LSZ又说:我懒得编题目背景了
于是就有了这道无聊的题目
一个筐初始为空,有一些增加和删除数的操作,还有一些询问当前第K大的数是几
Input Format
第一行一个整数M,表示操作的数目
下面M行,每行一个操作:
L k 输出第k大的数,如果筐中元素不够k个则输出0
S p q 删除筐中[p,q]这个闭区间里的所有数
Z x 向筐中增加x这个数
Output Format
对于每个L操作输出第k大的数
对于每个S操作输出本次删除了几个数
Hint
\(1 \leq M \leq 222222\)
其中有40%数据满足\(1 \leq M \leq 3333\)
所有其他数都是1到M之间的整数
Sample Input
9
Z 4
Z 5
L 1
S 5 7
Z 1
L 2
Z 1
L 3
S 1 1
Sample Output
5
1
1
1
2
FineArtz's solution
/* 无聊的LSZ */
#include <iostream>
using namespace std;
class Node{
public:
Node *p = nullptr, *s[2] = {nullptr, nullptr};
int key = 0, size = 1, num = 1;
Node(int k) : key(k) { p = s[0] = s[1] = nullptr; size = num = 1; }
bool isRight() { return p->s[1] == this;}
Node *link(int w, Node *x){
s[w] = x;
if (x) x->p = this;
return this;
}
void update(){
size = num + (s[0] ? s[0]->size : 0) + (s[1] ? s[1]->size : 0);
}
};
Node *root = nullptr;
void rotate(Node *p){
Node *q = p->p->p;
if (p->isRight())
p->link(0, p->p->link(1, p->s[0]));
else
p->link(1, p->p->link(0, p->s[1]));
p->p->update();
if (q)
q->link(q->s[1] == p->p, p);
else{
p->p = nullptr;
root = p;
}
}
void splay(Node *p, Node *t = nullptr){
while (p->p != t && p->p->p != t){
if (p->isRight() == p->p->isRight()){
rotate(p->p);
rotate(p);
}
else{
rotate(p);
rotate(p);
}
}
if (p->p != t)
rotate(p);
p->update();
}
Node *find(int x){
Node *p = root;
while (p && p->key != x)
p = p->s[p->key < x];
if (p) splay(p);
return p;
}
void insert(int x){
if (!root){
root = new Node(x);
return;
}
if (find(x)){
++root->num;
root->update();
return;
}
Node *p = root, *q;
while (p){
q = p;
p = p->s[p->key < x];
}
p = new Node(x);
q->link(q->key < x, p);
splay(p);
}
Node *findk(int k){
if (root->size < k)
return nullptr;
Node *p = root;
while (!(((p->s[0] ? p->s[0]->size : 0) < k) && ((p->s[0] ? p->s[0]->size : 0) + p->num >= k))){
if (!p->s[0]){
k -= p->num;
p = p->s[1];
}
else{
if (p->s[0]->size >= k)
p = p->s[0];
else{
k -= (p->s[0]->size + p->num);
p = p->s[1];
}
}
}
if (p) splay(p);
return p;
}
Node *prev(){
Node *p = root->s[0];
if (!p)
return nullptr;
while (p->s[1])
p = p->s[1];
splay(p);
return p;
}
Node *succ(){
Node *p = root->s[1];
if (!p)
return nullptr;
while (p->s[0])
p = p->s[0];
splay(p);
return p;
}
int del(int l, int r){
int ret = 0;
if (!find(l)){
insert(l);
--ret;
}
Node *p = prev();
if (!find(r)){
insert(r);
--ret;
}
Node *q = succ();
if (!p && !q){
ret += root->size;
root = nullptr;
return ret;
}
if (!p){
if (root->s[0])
ret += root->s[0]->size;
root->s[0] = nullptr;
root->update();
return ret;
}
if (!q){
splay(p, 0);
if (root->s[1])
ret += root->s[1]->size;
root->s[1] = nullptr;
root->update();
return ret;
}
splay(p, q);
if (p->s[1])
ret += p->s[1]->size;
p->s[1] = nullptr;
p->update();
q->update();
return ret;
}
void dispose(Node *p){
if (!p) return;
dispose(p->s[0]);
dispose(p->s[1]);
delete p;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int m;
cin >> m;
while (m--){
char ch;
int x, y;
cin >> ch;
switch(ch){
case 'L':{
cin >> x;
if (!root || root->size < x)
cout << "0\n";
else{
findk(root->size - x + 1);
cout << root->key << '\n';
}
break;
}
case 'S':
cin >> x >> y;
cout << del(x, y) << '\n';
break;
case 'Z':
cin >> x;
insert(x);
break;
default:
break;
}
}
dispose(root);
return 0;
}