在抗日战争期间,华北平原广大地区进行了大规模的隧道战。 一般来说,通过隧道连接的村庄排成一列。 除了两端,每个村庄都与两个相邻的村庄直接相连。
入侵者经常对一些村庄发动袭击并摧毁其中的部分隧道。 八路军指挥官要求最新的隧道和村庄连接状态。 如果某些村庄严重隔离,必须立即恢复连接!
Input
输入的第一行包含两个正整数n和m(n,m≤50,000),表示村庄和事件的数量。 接下来的m行中的每一行描述一个事件。
以下所示的不同格式描述了三种不同的事件:
D x:第x个村庄被毁。
Q x:指挥官询问第x个村庄与其直接或间接相关的村庄数量。
R:最后毁坏的村庄被重建了。
Output
按顺序输出每个指挥官询问的答案。
Sample Input
7 9
D 3
D 6
D 5
Q 4
Q 5
R
Q 4
R
Q 4
Sample Output
1
0
2
4
线段树维护一个最长的数字的区间,WA点:一个点可以反复被删除
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
char ch[10];
struct node
{
int l, r;
} tree[50010 * 4];
void build(int x, int y, int z)
{
tree[z].l = tree[z].r = y - x + 1;
if (x == y)
return;
int mid = (x + y) / 2;
build(x, mid, z << 1);
build(mid + 1, y, z << 1 | 1);
}
void getsum(int l, int x, int y, int z, int num)
{
if (l < x || l > y)
return;
if (x == y)
{
tree[z].l = tree[z].r = num;
return;
}
int mid = (x + y) / 2;
getsum(l, x, mid, z << 1, num);
getsum(l, mid + 1, y, z << 1 | 1, num);
tree[z].l = tree[z << 1].l;
tree[z].r = tree[z << 1 | 1].r;
if (tree[z].l == mid - x + 1)
tree[z].l += tree[z << 1 | 1].l;
if (tree[z].r == y - mid)
tree[z].r += tree[z << 1].r;
}
int query(int l, int x, int y, int z)
{
int mid = (x + y) / 2;
if (x == y || tree[z].l == y - x + 1)
return tree[z].l;
if (l < mid + 1 - tree[z << 1].r)
return query(l, x, mid, z << 1);
if (l > mid + tree[z << 1 | 1].l)
return query(l, mid + 1, y, z << 1 | 1);
return tree[z << 1].r + tree[z << 1 | 1].l;
}
int n,m,k;
int main()
{
while (~scanf("%d %d", &n, &m))
{
build(1, n, 1);
stack<int>sta;
while (m--){
cin>>ch;
if (ch[0] == 'D'){
scanf("%d", &k);
sta.push(k);
getsum(k, 1, n, 1, 0);
}
else if (ch[0] == 'R'){
k = sta.top();
sta.pop();
getsum(k, 1, n, 1, 1);
}
else{
cin>>k;
cout<<query(k, 1, n, 1)<<endl;
}
}
}
system("pause");
return 0;
}