一段区间上有一段连续的房子,每次可以消灭一个房子,修复一个房子,询问某一个房子所在的区间的长度
一个简单的线段树题
用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; }