题意:有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 ",max(0,ans)); } } } }