一段区间上有一段连续的房子,每次可以消灭一个房子,修复一个房子,询问某一个房子所在的区间的长度
一个简单的线段树题
用splay写的话也很简单的,因为能正好对应splay的一些基本操作
(别人的板子是坠吼的
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
const int maxn = 51234;
struct Node {
Node*ch[2], *p;
int size;
Node() {
size = 0;
}
bool d() {
return this == p->ch[1];
}
void setc(Node*c, int d) {
ch[d] = c;
c->p = this;
}
void relax();
void upd() {
size = ch[0]->size + ch[1]->size + 1;
}
} Tnull, *null = &Tnull;
Node mem[maxn];
Node *make(int v) {
Node *C=&mem[v];
C->ch[0] = C->ch[1] = null;
C->size = 1;
return C;
}
Node*build(int l, int r) {
if (l > r)
return null;
int m = (l + r) >> 1;
Node*t = make(m);
t->setc(build(l, m-1), 0);
t->setc(build(m + 1, r), 1);
t->upd();
return t;
}
Node*root;
void rot(Node*t) {
Node*p = t->p;
int d = t->d();
p->p->setc(t, p->d());
p->setc(t->ch[!d], d);
t->setc(p, !d);
p->upd();
if (p == root)
root = t;
}
void splay(Node*t, Node*f = null) {
while (t->p != f) {
if (t->p->p == f)
rot(t);
else
t->d() == t->p->d() ? (rot(t->p), rot(t)) : (rot(t), rot(t));
}
t->upd();
}
int n;
int times[maxn];
void dist(int id){
Node *rot = &mem[id];
splay(rot);
for(int i=0;i<2;i++){
if(rot->ch[i] != null){
rot->ch[i]->p=null;
rot->ch[i]=null;
}
}
rot->upd();
times[id]++;
}
int query(int id){
if(times[id] > 0)
return 0;
Node *rot = &mem[id];
splay(rot);
return rot->size;
}
void Link(int l,int r){
Node *L = &mem[l];
Node *R = &mem[r];
splay(L);
splay(R);
L->setc(R,1);
L->upd();
}
void fix(int id){
times[id]--;
if(times[id]!=0)
return;
if(id > 1 && times[id-1]==0){
Link(id-1,id);
}
if(id < n && times[id+1]==0){
Link(id,id+1);
}
}
stack<int> S;
int main() {
int m;
while(~scanf("%d %d",&n,&m)){
while(S.empty()==false)
S.pop();
memset(times,0,sizeof(times));
root = build(1, n);
root->p = null;
char ord[4];
int id;
while(m--){
scanf("%s",ord);
if(*ord == 'R'){
id = S.top();
S.pop();
fix(id);
}
else{
scanf("%d",&id);
if(*ord == 'Q'){
printf("%d\n",query(id));
}
else{
dist(id);
S.push(id);
}
}
}
}
return 0;
}