HDU-1394 線段樹+逆序數

  • 思路
    查詢該數到n已經插入的個數,再單點更新該數sum[root]=1,最後求出所有的逆序數的個數。
    每次換到後面,說明小於a[i]有a[i]個數 大於a[i]有n-a[i]-1個數 說明少了有a[i]個逆序數 多了n-a[i]-1個逆序數。
import java.util.Scanner;

public class Main_HDU1394 {
	static int n;
	static int[] a = new int[5005];
	static int[] sum = new int[5005<<2];
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()) {
			n = sc.nextInt();
			build(1,n,1);
			int res = 0;
			for(int i=1;i<=n;i++) {
				a[i] = sc.nextInt();
				res += query(a[i]+1,n,1,n,1);
				update(a[i]+1,1,n,1);
			}
			int ans = 99999999;
			for(int i=1;i<=n;i++) {
				res = res-a[i]+n-a[i]-1;  //將a[i]換到後面    小於a[i]有a[i]個數  大於a[i]有n-a[i]-1個數  說明少了有a[i]個逆序數  多了n-a[i]-1個逆序數  
				ans = Math.min(ans, res);
			}
			System.out.println(ans);
		}	
	}
	public static void build(int l,int r,int root) {
		sum[root] = 0;
		if(l==r) return;
		int m = (l+r)>>1;
		build(l,m,root<<1);
		build(m+1,r,root<<1|1);
	}
	public static void update(int x,int l,int r,int root) {
		if(l==r) {
			sum[root] = 1;    //插入該數
			return;
		}
		int m = (l+r)>>1;
		if(x<=m) 
			update(x,l,m,root<<1);
		else 
			update(x,m+1,r,root<<1|1);
		sum[root] = sum[root<<1] + sum[root<<1|1];
	}
	public static int query(int x,int y,int l,int r,int root) {
		if(x<=l&&r<=y) {
			return sum[root];   //查詢[a[i]+1,n]已經插入的個數
		}
		int m = (l+r)>>1;
		int res = 0;
		if(x<=m)
			res += query(x,y,l,m,root<<1);
		if(y>m)
			res += query(x,y,m+1,r,root<<1|1);
		return res;
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章