[洛谷][P1503][鬼子进村][Treap]
题意就不解释了吧。
看到这道题,一开始YY把所有点加进treap里面,然后完全跟着操作走,应该是可做的。[在treap里面找连续的一段应该很简单,只要有一定代码能力都行|||||||吧。。。。]
可不幸的因为本人太弱,不想写,就不得不YY其它的做法,我们可以发现,被困士兵能通过的房子组成的序列的两个端点为被毁灭的两个房屋。[左端点有可能为零,即最左端,右端点可能为n+1,即最右端] 所以我们每次把被删除的端点加入treap,对于查询,我们查当前士兵的前驱和后继即可
上代码 :
#include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> #include<string> #include<cmath> #include<cctype> const int N = 5e4 + 7,INF = 0x7fffffff; #define R121() ((rand()<<12)+(rand()<<7)+rand()) #include<bitset> #define R233() (R121() % 456454541 + R121() % 452112101 + R121() % 121231 + 1) using std :: bitset; int n,m,v; class Treap { private : struct Node { Node *son[2]; int size,data,hr; Node () {} Node (int data,Node *fl) : data(data) { son[0] = son[1] = fl; size = 1; hr = R233(); } void update () { size = son[0] -> size + son[1] -> size + 1;} }*Null,*root,*pool,meme[N]; int ball; void rotate (Node *&T,bool v) { Node *Tt = T -> son[v]; T -> son[v] = Tt -> son[v^1]; Tt -> son[v^1] = T; T -> update(); Tt -> update(); T = Tt; } void Insert (Node *&T) { if(T == Null) { T = new (pool++) Node (ball,Null); return ; } bool v = T -> data < ball; Insert (T -> son[v]); if(T -> son[v] -> hr < T -> hr) rotate (T , v); else T -> update(); } void Delete (Node *&T) { if(T == Null) return; if(T -> data == ball) { if(T -> son[0] == Null || T -> son[1] == Null) { bool v = T -> son[1] != Null; T = T -> son[v]; return ; } bool v = T -> son[0] -> hr > T -> son[1] -> hr; rotate (T , v); Delete (T -> son[v^1]); } else { bool v = ball > T -> data; Delete (T -> son[v]); } T -> update(); } int Subsequent (Node *&T) { if(T == Null) return n+1; if(T -> data <= ball) return Subsequent (T -> son[1]); // if(T -> data + 1 <= ball) return T -> data; // if(T -> data < ball) int k = Subsequent (T -> son[0]); return k == n + 1 ? T -> data : k; } int Precursor (Node *&T) { if(T == Null) return 0; if(T -> data >= ball) return Precursor (T -> son[0]); int k = Precursor (T -> son[1]); return k == 0 ? T -> data : k; } public : Treap () { Null = new Node(); Null -> size = 0; } void clear () { pool = meme; root = Null; } void Ins (int xxx) { ball = xxx; Insert(root); } void Del (int xxx) { ball = xxx; Delete(root); } int Sub (int xxx) { ball = xxx; return Subsequent(root); } int Pre (int xxx) { ball = xxx; return Precursor(root); } }treap; char opt[N]; bitset<N>vis; int stk[N],top; int main () { scanf("%d%d",&n,&m); treap.clear(); for(int i=1;i<=m;++i) { scanf("%s",opt); if(opt[0] == 'R') treap.Del(stk[top--]),vis.flip(stk[top+1]); else { scanf("%d",&v); if(opt[0] == 'D') { if(!vis.test(v)) treap.Ins(v),vis.flip(v),stk[++top]=v; } else if(opt[0] == 'Q') { if(vis.test(v)) puts("0"); else printf("%d\n", treap.Sub(v) - treap.Pre(v) - 1); } } } return 0; }
That is all. Thank you for watching!