题意:有n座房子,起初都是完好的,有m次操作,可以销毁i号房屋,可以重建最后一个销毁的房屋,可以查询i号房屋和几个房屋直接或间接相连。
题解:假设 1 2 3 4 5 6 7 8 中3 和7 已经摧毁,现在查询5,那么就是1 - 5中最靠右的毁坏的是3,5 - 8 中最靠左毁坏的的是7,那么答案就是7 - 3 - 1 = 3,当然如果刚好查询的那个已经摧毁那么就不用- 1了,所以需要维护每一个结点的最靠近它的两个左右摧毁点
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<stack>
#include<cstdlib>
#include<queue>
#include<set>
#include<vector>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-10
typedef long long LL;
const int MAXN = 5e4 + 5;
const int mod = 998244353;
int stl[MAXN << 2],str[MAXN << 2];
int n;
void pushup(int o) {
stl[o] = max(stl[o << 1], stl[o << 1 | 1]);
str[o] = min(str[o << 1], str[o << 1 | 1]);
}
void build(int o,int l,int r) {
if (l == r) {
stl[o] = 0;
str[o] = n + 1;
} else {
int mid = (l + r) >> 1;
build(o << 1, l, mid);
build(o << 1 | 1, mid + 1, r);
pushup(o);
}
}
void update(int o,int l,int r,int pos,int id) {// id用来判断是破坏还是修复
if (l == r) {
if (id)
{
stl[o] = max(stl[o],id);
str[o] = min(str[o],id);
}
else {
stl[o] = 0;
str[o] = n + 1;
}
} else {
int mid = (l + r) >> 1;
if (pos <= mid) update(o << 1, l, mid, pos, id);
else update(o << 1 | 1, mid + 1, r, pos, id);
pushup(o);
}
}
int query_r(int o,int l,int r,int ql,int qr) {
if(ql <= l && r <= qr) return str[o];
int mid = (l + r) >> 1;
int ans = n + 1;
if(ql <= mid) ans = min(ans,query_r(o << 1,l,mid,ql,qr));
if(qr > mid) ans = min(ans,query_r(o << 1 | 1,mid + 1,r,ql,qr));
return ans;
}
int query_l(int o,int l,int r,int ql,int qr) {
if(ql <= l && r <= qr) return stl[o];
int mid = (l + r) >> 1;
int ans = 0;
if(ql <= mid) ans = max(ans,query_l(o << 1,l,mid,ql,qr));
if(qr > mid) ans = max(ans,query_l(o << 1 | 1,mid + 1,r,ql,qr));
return ans;
}
int main() {
int m;
while (~scanf("%d %d", &n, &m)) {
build(1, 1, n);
char s[5];
int c;
stack<int> sta;
while (m--) {
scanf("%s", s);
if (s[0] == 'D') {
scanf("%d", &c);
update(1, 1, n, c, c);
sta.push(c);
}
else if(s[0] == 'R') {
c = sta.top();
sta.pop();
update(1,1,n,c,0);
}
else {
scanf("%d",&c);
int ans = query_r(1,1,n,c,n) - query_l(1,1,n,1,c) - 1;
//printf("%d %d", query_r(1,1,n,c,n) , query_l(1,1,n,1,c));
printf("%d\n",max(0,ans));
}
}
}
}