HDU-1540 樹狀數組+二分查找 Java

個人覺得用樹狀數組更容易理解,詢問一個點有多少個連接的點,就找到右邊被摧毀的點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;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章