题意:有n个村庄,编号分别为1-n;由于战争会破坏村庄,但是我们也会修复;
D x代表村庄x被破坏;
Q x是求与x相连的有几个没有被破坏;
R 是修复最后一次被破坏的村庄;
接下来有m个操作,对于每次Q操作输出结果;
由于修复的是最后一次被破坏的所以要用stack
接下来看代码吧,加个图好理解一点
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<stack> using namespace std; #define INF 0xfffffff #define N 50050 #define Lson r<<1 #define Rson r<<1|1 struct SegmentTree { int L, R, sum, lsum, rsum; int Mid() { return (L+R)>>1;} int len() { return R-L+1; } } a[N<<2]; void Build(int r, int L, int R) { a[r].L = L, a[r].R = R; a[r].sum = a[r].lsum = a[r].rsum = a[r].len();///刚开始的时候一定是区间所在长度; if(L == R) return; Build(Lson, L, a[r].Mid()); Build(Rson, a[r].Mid()+1, R); } void Up(int r)///当下面的节点发生变化的时候我们要往上不断更新 { a[r].lsum = a[Lson].lsum; a[r].rsum = a[Rson].rsum; if(a[r].lsum == a[Lson].len()) a[r].lsum += a[Rson].lsum; if(a[r].rsum == a[Rson].len()) a[r].rsum += a[Lson].rsum; a[r].sum = max(max(a[Lson].lsum, a[Rson].rsum),a[Lson].rsum+a[Rson].lsum); } void Update(int r, int pos, int flag)///flag 为0表示破坏,1表示修复; {///因为是直接更新到叶子节点的所以不需再往下更新,但是要往上更新; if(a[r].L == a[r].R && a[r].L==pos) { a[r].sum = a[r].lsum = a[r].rsum = flag; return ; } if(pos <= a[r].Mid()) Update(Lson, pos, flag); else if(pos > a[r].Mid()) Update(Rson, pos, flag); Up(r); } int Query(int r, int pos) { if(a[r].sum == 0)return 0; if(pos < a[r].L + a[r].lsum) return a[r].lsum;///在最左边 if(pos > a[r].R - a[r].rsum) return a[r].rsum;///在最右边 if(pos > a[Lson].R - a[Lson].rsum && pos < a[Rson].L + a[Rson].lsum )///在中间部分; return a[Lson].rsum + a[Rson].lsum; if(pos <= a[r].Mid()) return Query(Lson, pos);///在左半边而非最左边; else return Query(Rson, pos);///在右半边而非最右边; } int main() { int n, m, x; char s[110]; while(scanf("%d %d", &n, &m)!=EOF) { Build(1, 1, n); stack<int> sta; for(int i=1; i<=m; i++) { scanf("%s", s); if(s[0] == 'D') { scanf("%d", &x); Update(1, x, 0); sta.push(x);///按破坏顺序一个一个的加入栈中 } else if(s[0] == 'Q') { scanf("%d", &x); printf("%d ", Query(1, x)); } else { x = sta.top(); sta.pop(); Update(1, x, 1); } } } return 0; }