個人覺得用樹狀數組更容易理解,詢問一個點有多少個連接的點,就找到右邊被摧毀的點R和左邊被摧毀的點L,最終結果爲R-L-1.
import java.util.Arrays;
import java.util.Scanner;
public class Main_HDU1540 {
static int[] sum = new int[50005];
static int[] D = new int[50005];
static boolean[] vis = new boolean[50005];
static int n,m;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
Arrays.fill(sum, 0);
Arrays.fill(vis, true);
n = sc.nextInt();
m = sc.nextInt();
for(int i=1;i<=n;i++){
update(i,1);
}
int cnt = 1;
for(int i=1;i<=m;i++) {
String s = sc.next();
if(s.equals("D")) {
int x = sc.nextInt();
D[cnt++] = x;
if(vis[x]) {
update(x,-1);
vis[x] = false;
}
}else if(s.equals("Q")) {
int x = sc.nextInt();
if(!vis[x]) { //注意被摧毀的點
System.out.println(0);
}else {
int R = searchR(x);
int L = searchL(x);
System.out.println(R-L-1);
}
}else {
if(!vis[D[--cnt]]) {
vis[D[cnt]] = true;
update(D[cnt],1);
}
}
}
}
}
public static void update(int x,int d) {
for(int i=x;i<=n;i+=i&(-i)) {
sum[i] += d;
}
}
public static int get(int x) {
int ans = 0;
for(int i=x;i>=1;i-=i&(-i)) {
ans += sum[i];
}
return ans;
}
public static int searchR(int x) {
int l=x,r=n+1; //r得爲n+1,假入x爲7時右邊應爲8
while(l<r) {
int m = (l+r)>>1;
if(get(m)-get(x)==m-x) { //判斷m點總數與x點總數的差是否等於點差
l = m+1; //相等說明[x+1,m]之間都是沒有被摧毀
}else {
r = m; //不相等說明[x+1,m]之間每個點都有可能是被摧毀的
}
}
return r;
}
public static int searchL(int x) {
int l=0,r=x; //l得爲0,假如x爲1時左邊應爲0
while(l<r) {
int m = (l+r)>>1;
if(get(x)-get(m)==x-m) { //跟上是一樣的道理
r = m;
}else {
l = m+1;
}
}
return l;
}
}