题意:给定了初始的状态:有n个村庄连成一条直线,现在有三种操作: 1.摧毁一个村庄 2.询问某个村庄,输出与该村庄相连的村庄数量(包括自己) 3.修复被摧毁的村庄,优先修复最近被摧毁的..............

分析:用SBT做的话,摧毁村庄就插入,修复就移除,如果要询问的话:找到第一个大于等于该村庄编号和第一个小于等于该村庄编号的,等价于找到了联通在一起的村庄。

朴素的做法可以 set + stack + 二分 搞之.................

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <climits>//形如INT_MAX一类的
#define MAX 55555
#define INF 0x7FFFFFFF
#define REP(i,s,t) for(int i=(s);i<=(t);++i)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define L(x) x<<1
#define R(x) x<<1|1
# define eps 1e-5
//#pragma comment(linker, "/STACK:36777216") ///传说中的外挂
using namespace std; struct sbt {
int l,r,s,key;
} tr[MAX];
int top , root;
void left_rot(int &x) {
int y = tr[x].r;
tr[x].r = tr[y].l;
tr[y].l = x;
tr[y].s = tr[x].s; //转上去的节点数量为先前此处节点的size
tr[x].s = tr[tr[x].l].s + tr[tr[x].r].s + 1;
x = y;
} void right_rot(int &x) {
int y = tr[x].l;
tr[x].l = tr[y].r;
tr[y].r = x;
tr[y].s = tr[x].s;
tr[x].s = tr[tr[x].l].s + tr[tr[x].r].s + 1;
x = y;
} void maintain(int &x,bool flag) {
if(flag == 0) { //左边
if(tr[tr[tr[x].l].l].s > tr[tr[x].r].s) {//左孩子左子树size大于右孩子size
right_rot(x);
} else if(tr[tr[tr[x].l].r].s > tr[tr[x].r].s) {//左孩子右子树size大于右孩子size
left_rot(tr[x].l);
right_rot(x);
} else return ;
} else { //右边
if(tr[tr[tr[x].r].r].s > tr[tr[x].l].s) { //右孩子的右子树大于左孩子
left_rot(x);
} else if(tr[tr[tr[x].r].l].s > tr[tr[x].l].s) { //右孩子的左子树大于左孩子
right_rot(tr[x].r);
left_rot(x);
} else return ;
}
maintain(tr[x].l,0);
maintain(tr[x].r,1);
} void insert(int &x,int key) {
if(x == 0) { //空节点
x = ++ top;
tr[x].l = tr[x].r = 0;
tr[x].s = 1;
tr[x].key = key;
} else {
tr[x].s ++;
if(key < tr[x].key) insert(tr[x].l,key);
else insert(tr[x].r,key);
maintain(x,key >= tr[x].key);
}
} int remove(int &x,int key) {
int k;
tr[x].s --;
if(key == tr[x].key || (key < tr[x].key && tr[x].l == 0) || (key > tr[x].key && tr[x].r == 0)) {
k = tr[x].key;
if(tr[x].l && tr[x].r) {
tr[x].key = remove(tr[x].l,tr[x].key + 1);
} else {
x = tr[x].l + tr[x].r;
}
} else if(key > tr[x].key) {
k = remove(tr[x].r,key);
} else if(key < tr[x].key) {
k = remove(tr[x].l,key);
}
return k;
} int pred(int &x,int y,int key)
//前驱 小于
{
if(x == 0) return tr[y].key ;
if(tr[x].key < key) return pred(tr[x].r,x,key);
else if(tr[x].key > key) return pred(tr[x].l,y,key);
else return key;
}//pred(root,0,key)
int succ(int &x,int y,int key) { //后继 大于
if(x == 0) return tr[y].key;
if(tr[x].key > key) return succ(tr[x].l,x,key);
else if(tr[x].key < key) return succ(tr[x].r,y,key);
else return key;
} int n,m;
char c;
int st[MAX];
int head = 0;
int main() {
root = 0;
top = 0;
int b;
scanf("%d%d",&n,&m);
for(int i=0; i<m; i++) {
cin >> c;
if(c == 'D') {
scanf("%d",&b);
st[head++] = b;
insert(root,b);
}
if(c == 'R') {
remove(root,st[--head]);
}
if(c == 'Q') {
scanf("%d",&b);
int pre = pred(root,0,b);
int suc = succ(root,0,b);
if(suc == 0) suc = n+1;
if(pre == suc) {
puts("0");
continue;
}
printf("%d\n",suc - pre - 1);
}
}
return 0;
}

POJ 2892 Tunnel Warfare (SBT + stack)的更多相关文章

  1. POJ 2892 Tunnel Warfare(线段树单点更新区间合并)

    Tunnel Warfare Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 7876   Accepted: 3259 D ...

  2. hdu 1540/POJ 2892 Tunnel Warfare 【线段树区间合并】

    Tunnel Warfare                                                             Time Limit: 4000/2000 MS ...

  3. POJ 2892 Tunnel Warfare

    传送门 很神奇的一道题,可以用线段树搞,为了练习treap所以拿treap写了. 其实根据询问,删除那个标号就加入平衡树,然后找到最大的和最小的就好了. 一些很烦人的小细节. //POJ 2892 / ...

  4. HDU 1540 / POJ 2892 Tunnel Warfare (单点更新,区间合并,求包含某点的最大连续个数)

    题意:一条线上有n个点,D x是破坏这个点,Q x是表示查询x所在的最长的连续的点的个数,R是恢复上一次破坏的点. 思路:这题的关键是查询. 将被毁的村庄看成空位,当查询某个点的时候,如果我们知道它左 ...

  5. poj 2892 Tunnel Warfare(线段树)

    Tunnel Warfare Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 7499   Accepted: 3096 D ...

  6. HDU 1540 POJ 2892 Tunnel Warfare

    线段树 区间合并 单点修改 区间查询.又是1秒钟构思,差错查了好久... ... 发现一个int型的定义成了char型,打脸. #include <stdio.h> #include &l ...

  7. POJ 2892 Tunnel Warfare(树状数组+二分)

    题目链接 二分求上界和下界,树状数组.注意特殊情况. #include <cstring> #include <cstdio> #include <string> ...

  8. POJ 2892 Tunnel Warfare || HDU 1540(树状数组+二分 || 线段树的单点更新+区间查询)

    点我看题目 题意 :N个村子连成一条线,相邻的村子都有直接的地道进行相连,不相连的都由地道间接相连,三个命令,D x,表示x村庄被摧毁,R  ,表示最后被摧毁的村庄已经重建了,Q x表示,与x直接或间 ...

  9. 【POJ】2892 Tunnel Warfare

    [算法]平衡树(treap) [题解]treap知识见数据结构 在POJ把语言从G++换成C++就过了……??? #include<cstdio> #include<algorith ...

随机推荐

  1. WPF笔记(2.6 ViewBox)——Layout

    原文:WPF笔记(2.6 ViewBox)--Layout 在Canvas外面包一层ViewBox,可以使Canvas内的控件填充整个ViewBox,并随着ViewBox的大小变化而同步变化,这是因为 ...

  2. UML_活动图

    一.活动图的组成元素 Activity Diagram Element 1.活动状态图(Activity) 2.动作状态(Actions) 3.动作状态约束(Action Constraints) 4 ...

  3. 【LeetCode练习题】Swap Nodes in Pairs

    Swap Nodes in Pairs Given a linked list, swap every two adjacent nodes and return its head. For exam ...

  4. HDU-1016-素数环

    /* 将1-n个数放在环中,保证相邻的两个数的和是素数 第一个数字永远是1 就这两个约束条件 第一个难点是计算素数: 参考文献: http://c.biancheng.net/cpp/html/254 ...

  5. 【转】Linux查看CPU和内存使用情况

    =====================================top============================================== 在系统维护的过程中,随时可 ...

  6. poj 3370 Halloween treats(鸽巢原理)

    Description Every year there is the same problem at Halloween: Each neighbour is only willing to giv ...

  7. http://home.cnblogs.com/

    说起编辑器,可能大部分人要推荐的是Vim和Emacs,本人用过Vim,功能确实强大,但是不是很习惯,之前一直有朋友推荐SUblime Text 2这款编辑器,然后这段时间就试了一下,就深深地喜欢上这款 ...

  8. Js数组的操作push,pop,shift,unshift等方法详细介绍

    js中针对数组操作的方法还是比较多的,今天突然想到来总结一下,也算是温故而知新吧.不过不会针对每个方法进行讲解,我只是选择其中的一些来讲. 首 先来讲一下push和pop方法,这两个方法只会对数组从尾 ...

  9. wpf msdn在线地址http://msdn.microsoft.com/zh-cn/library/ms752324(v=vs.110).aspx

    http://msdn.microsoft.com/zh-cn/library/ms752324(v=vs.110).aspx

  10. html image -- data:image/png;base64

    1,  data:image/png;base64 <!DOCTYPE HTML> <html> <head> <meta http-equiv=" ...