poj 2892 stl或线段树

标准解法应该是线段树,这里提供另一种思路:将“断点”(即被摧毁的村庄)放入stl的容器(我用的是set)中维护,对于每次查询,只要找这个数在哪两个断点之间即可,写起来轻松愉快。

PS:hdu上的数据略坑,同一个村庄可以被摧毁多次,恢复的时候一次恢复就可以让它不再是断点,但是第一次恢复以后剩下几次也是需要恢复的...所以不能把它被摧毁的记录删除,另外没有被摧毁的村庄时也有R操作。poj上的数据比较规范,符合实际情况,没有上面的奇怪数据。

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <stack>
 6 #include <set>
 7 using namespace std;
 8
 9 set<int> s;
10 set<int>::iterator it;
11 stack<int> st;
12
13 int main ()
14 {
15     int n, m;
16     while ( scanf("%d%d", &n, &m) != EOF )
17     {
18         while ( !st.empty() ) st.pop();
19         s.clear();
20         char op[2];
21         int x;
22         while ( m-- )
23         {
24             scanf("%s", op);
25             if ( op[0] == ‘D‘ )
26             {
27                 scanf("%d", &x);
28                 s.insert(x);
29                 st.push(x);
30             }
31             else if ( op[0] == ‘Q‘ )
32             {
33                 scanf("%d", &x);
34                 if ( s.find(x) != s.end() )
35                 {
36                     printf("0\n");
37                 }
38                 else
39                 {
40                     int l = 1, r = n;
41                     it = s.upper_bound(x);
42                     if ( it != s.end() )
43                     {
44                         r = (*it) - 1;
45                     }
46                     if ( it != s.begin() )
47                     {
48                         it--;
49                         l = (*it) + 1;
50                     }
51                     printf("%d\n", r - l + 1);
52                 }
53             }
54             else
55             {
56                 if ( st.empty() ) continue;
57                 int tmp = st.top();
58                 st.pop();
59                 s.erase(tmp);
60             }
61         }
62     }
63     return 0;
64 }
时间: 2024-10-10 08:49:59

poj 2892 stl或线段树的相关文章

HDU 1540 &amp;&amp; POJ 2892 Tunnel Warfare (线段树,区间合并).

~~~~ 第一次遇到线段树合并的题,又被律爷教做人.TAT. ~~~~ 线段树的题意都很好理解吧.. 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1540 http://poj.org/problem?id=2892 ~~~~ 我的代码:200ms #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #defin

POJ训练计划2777_Count Color(线段树/成段更新/区间染色)

解题报告 题意: 对线段染色,询问线段区间的颜色种数. 思路: 本来直接在线段树上染色,lz标记颜色.每次查询的话访问线段树,求出颜色种数.结果超时了,最坏的情况下,染色可以染到叶子节点. 换成存下区间的颜色种数,这样每次查询就不用找到叶子节点了,用按位或来处理颜色种数. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace

POJ训练计划1177_Picture(扫描线/线段树+离散)

解题报告 题意: 求矩形周长和. 思路: 左扫上扫,扫过了. #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; struct Seg { int lx,rx,ly,ry,h,v; friend bool operator < (Seg a,Seg b) { re

POJ训练计划2828_Buy Tickets(线段树/单点更新)

解题报告 题意: 插队完的顺序. 思路: 倒着处理数据,第i个人占据第j=pos[i]+1个的空位. 线段树维护区间空位信息. #include <iostream> #include <cstdio> #include <cstring> using namespace std; struct node { int x,v; } num[201000]; int sum[1000000],ans[201000]; void cbtree(int rt,int l,in

POJ 1151 Atlantis 扫描线+线段树

点击打开链接 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17252   Accepted: 6567 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of pa

POJ 2155 二维线段树

POJ 2155  二维线段树 思路:二维线段树就是每个节点套一棵线段树的树. 刚开始因为题目是求A[I,J],然后在y查询那直接ans^=Map[i][j]的时候没看懂,后面自己把图画出来了才理解. 因为只有0和1,所以可以用异或来搞,而不需要每次都需要修改. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #incl

POJ 2828 Buy Tickets (线段树)

题目大意: 排队有人插队,每一次都插到第 i 个人的后面. 最后输出顺序. 思路分析: 你会发现,如果反向处理的话,你就知道这个人是第几个了. 那么问题一下子就简化了. 就是在线段树上找第几个空位置就行了. #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <vector> #define lson num<<1

POJ 2155 二维线段树 经典的记录所有修改再统一遍历 单点查询

本来是想找一个二维线段树涉及懒惰标记的,一看这个题,区间修改,单点查询,以为是懒惰标记,敲到一半发现这二维线段树就不适合懒惰标记,你更新了某段的某列,但其实其他段的相应列也要打标记,但因为区间不一样,又不好打...也可能是我这是在套用一维线段树的思想,还有更好的二维线段树懒惰标记方法 反正到现在我还没搞定二维线段树的懒惰标记,因为这道题不用懒惰标记,因为是二进制序列,区间修改仅限于翻转操作,那就只要记录每次操作,最后查询的时候从上往下把所有修改都来上一遍,就可以了.就类似于树状数组的第二种用法,

POJ 2828 Buy Tickets 线段树解法

此题应用线段树的方法非常巧妙.没做过真的难想得出是这么想的. 是一个逆向思维的运用. 其实一看到这道题目我就想到要运用逆向思维的了,但是就是没那么容易想通的. 思路: 1 要从后面往前更新线段树 2 线段树记录的是当前区间还剩下多少个记录空间 3 因为后面的插入会使得前面的插入往后退,那么前面插入的下标如果大于前面可以插入的空间,就需要往后退了. 好难理解的操作.仔细观察一下下面update这个函数吧. 二分地去查找适合的插入位置,把插入操作时间效率提高到 O(lgn),如果使用一般方法插入操作