这种题就是标准的模板题,只要一个Treap上去就AC了,所以没有什么价值,唯一的价值就是用来学习Treap前驱和后继函数在动态数据中的应用。
首先解释下题目意思:
输入n和m,你表示数轴的长度,当然这里的数轴是从1开始的正整数,m表示接下来有m个操作。
D x: The x-th village was destroyed.
就是摧毁数轴上的x值
Q x: The Army commands requested the number of villages that x-th
village was directly or indirectly connected with including itself.
询问x最左和最右没有被摧毁的两个数轴上点的距离.
R:
The village destroyed last was rebuilt.
重新修复最近一个被摧毁的点
Q x 的查询操作很容易让人想到平衡二叉树中的求前驱和后继函数,因此这题就解决了,
各种平衡二叉树均能推倒之,我是用Treap来写的。
具体的解法就是把D操作中的x insert到Treap中,R操作的时候就把最近的一次摧毁的点remove掉,
当然这里要另外开一个数组来记录所有被摧毁的点,便于查找最近被摧毁的点。
Q的时候就找前驱p和后继q,最后的答案就是q->key - p->key - 1;
这里开始的时候有个小技巧,就是把数轴的0点和n+1点也insert到Treap里面,
这样避免了求前驱和后继的时候返回的是null。
如果有不了解Treap(随机平衡二叉树)的可以见http://blog.csdn.net/acceptedxukai/article/details/6910685
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <set> #include <map> #include <ctime> #include <vector> #include <queue> using namespace std; #define LL long long const int N = 10005; const int MAX = 1<<30; class Treap { public : struct Node { int key,cnt,fix; Node *left,*right; Node(int e) : key(e),cnt(1),fix(rand()) {} }*root,*null; Treap() { null = new Node(MAX); null->cnt = 0; root = null->right = null->left = null; } //右旋 void right_rat(Node *&x) { Node *y = x->left; x->left = y->right; y->right = x; x = y; } //左旋 void left_rat(Node *&x) { Node *y = x->right; x->right = y->left; y->left = x; x = y; } void insert(Node *&x,int e) { if(x == null) { x = new Node(e); x->left = x->right = null; } else if(e < x->key) { insert(x->left,e); if(x->left->fix < x->fix)right_rat(x); } else if(e > x->key) { insert(x->right,e); if(x->right->fix < x->fix) left_rat(x); } else ++x->cnt; } //删除函数 void remove(Node *&x,int e) { if(x == null) return; else if(e <x->key) remove(x->left,e); else if(e > x->key) remove(x->right,e); else if(--x->cnt <= 0) { if(x->left == null || x->right == null) { Node *y = x; x = (x->left != null)? x->left : x->right; delete y; } else { if(x->left->fix < x->right->fix) { right_rat(x); remove(x->right,e); } else { left_rat(x); remove(x->left,e); } } } } //前驱 Node* Pred(Node* x,Node* y,int e) { if (x == null) return y; if (e < x->key) return Pred(x->left,y,e); return Pred(x->right,x,e); } //后继 Node *Succ(Node *x,Node *y,int e) { if(x == null) return y; if(e <= x->key) return Succ(x->left,x,e); return Succ(x->right,y,e); } int count(int e) { Node *p = Pred(root,null,e);//求前驱 Node *q = Succ(root,null,e);//求后继 return (q->key - p->key - 1) < 0 ? 0 : (q->key - p->key - 1); } }; int str[50005]; int main() { srand(time(0)); Treap tree; int n,m,p,cnt=0; tree.insert(tree.root,0);//插入0点 scanf("%d %d",&n,&m); tree.insert(tree.root,n+1);//插入n+1点 for(int i = 0 ; i < m ; i ++) { char ch[3]; scanf("%s",ch);//用字符串输入比较方便,char太麻烦了 if(strcmp(ch,"D") == 0) { scanf("%d",&p); str[cnt++]=p; tree.insert(tree.root,p); } else if(strcmp(ch,"Q") == 0) { scanf("%d",&p); printf("%d\n",tree.count(p)); } else { p = str[cnt-1]; cnt--; tree.remove(tree.root,p); } //getchar(); } return 0; }