HDU-1540

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540

题目大意:

一些村庄排成一排,编号1-N,只要中间没有被摧毁的村庄,两个村庄就算是连接在一起的,现在有三个操作
1.摧毁编号为X的村庄
2.询问与村庄X连接的村庄有几个
3.重建上一个被摧毁的村庄

思路

我们只要知道查询的村庄X,它的左边最近的一个被摧毁的村庄,和它右边最近的一个被摧毁的村庄,就可以知道与X相连的村庄个数
所以考虑使用线段树来维护区间内被摧毁的村庄的数量,查询时如果区间的断点数为0直接返回,否则进行递归,同时更新记录上述的两个坐标,然后根据最后的坐标分类讨论一下就是答案了
重建村庄弄个栈搞一搞就好了
题目的坑点有:
1.题目没说是多组,但其实是多组
2.村庄可以重复摧毁,但是重建只需一次即可

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <iostream>
#include <stack>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
#define wfor(i,j,k) for(i=j;i<k;++i)
#define mfor(i,j,k) for(i=j;i>=k;--i)
// void read(int &x) {
// char ch = getchar(); x = 0;
// for (; ch < '0' || ch > '9'; ch = getchar());
// for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
// }
const int maxn = 50005;
int tree[maxn << 2];
void push_up(int id)
{
tree[id] = tree[id << 1] + tree[id << 1 | 1];
}
void updata(int l, int r, int id, int pos, int number)//更新村庄状态,被摧毁就是1,没有就是0
{
if (l == r)
{
tree[id] = number;
return ;
}
int mid = (l + r) >> 1;
if (mid >= pos)
updata(l, mid, id << 1, pos, number);
else
updata(mid + 1, r, id << 1 | 1, pos, number);
push_up(id);
}
int flag = 0;
void query(int l, int r, int id, int pos, int &x, int &y)//x,y是距离查询目标最近的左右断点位置
{
if (flag)
return;
if (tree[id] == 0)//如果区间内没断点,那么直接返回
{
return ;
}
if (l == r)
{
if (tree[id] == 1)
{
if (l == pos)//如果查询目标就是被摧毁的直接返回,答案为0
{
flag = 1;
return ;
}
if (l <= pos)//更新x,y的值
x = max(x, l);
else
y = min(y, l);
}
return ;
}
int mid = (l + r) >> 1;
if (mid >= x)
query(l, mid, id << 1, pos, x, y);
if (mid < y)
query(mid + 1, r, id << 1 | 1, pos, x, y);
}
int des[maxn];//记录村庄是否被摧毁
int main()
{
std::ios::sync_with_stdio(false);
int n, m;
while (cin >> n >> m)
{
int i;
stack<int>last;
memset(tree, 0, sizeof(tree));
memset(des, 0, sizeof(des));
wfor(i, 0, m)
{
char c;
cin >> c;
if (c == 'D')
{
int pos;
cin >> pos;
last.push(pos);//将被摧毁的村庄压入栈中
des[pos] = 1;
updata(1, n, 1, pos, 1);
} else if (c == 'Q')
{
int pos;
cin >> pos;
int x = -1, y = 1e9;
flag = 0;
query(1, n, 1, pos, x, y);
if (flag)//查询村庄被摧毁的情况
{
cout << 0 << endl;
} else//分类讨论查询目标的左右断点的情况
{
int ans = 0;
if (x == -1 && y == 1e9)
{
ans = n;
} else if (x == -1)
{
ans = pos;
ans += y - pos - 1;
} else if (y == 1e9)
{
ans = pos - x;
ans += n - pos;
} else
{
ans += pos - x;
ans += y - pos - 1;
}
cout << ans << endl;
}
} else//重建村庄
{
while (des[last.top()] == 0)//如果村庄已经被重建则弹出找下一个
{
last.pop();
}
updata(1, n, 1, last.top(), 0);
des[last.top()] = 0;//标记村庄已经被重建
last.pop();
}
}
}
return 0;
}

本文标题:HDU-1540

文章作者:

发布时间:2019年04月27日 - 19:04

最后更新:2019年04月27日 - 20:04

原始链接:http://startcraft.cn/post/bdc85e4e.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------The End-------------