分桶法和平方分割

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

//超時= =
public class Main {
	public static void main(String args[]) throws IOException  {
		PrintWriter out=new PrintWriter(System.out);
		InputReader sc=new InputReader(System.in);
		int maxn=100100;
		int n=sc.nextInt();
		int m=sc.nextInt();
		int A[]=new int[maxn];
		int num[]=new int[maxn];
		int B=1000;//桶的容量
		ArrayList<Integer> bucket[]=new ArrayList[maxn/B];
		for(int i=0;i<maxn/B;i++) {
			bucket[i]=new ArrayList<Integer>();
		}
		for(int i=0;i<n;i++) {
			A[i]=sc.nextInt();
			bucket[i/B].add(A[i]);
			num[i]=A[i];
		}
		Arrays.sort(num,0,n);
		for(int i=0;i<n/B;i++) {
			Collections.sort(bucket[i]);
		}
		for(int i=0;i<m;i++) {
			int l=sc.nextInt()-1;
			int r=sc.nextInt();//尋找[l,r)區間內的第k大
			int k=sc.nextInt();
			int lb=-1,ub=n;
			int mid=0;
			while(ub-lb>1) {
				mid=(lb+ub)/2;
				//out.println(mid);
				int x=num[mid];
				//out.println(x);
				int c=0;
				int tl=l,tr=r;
				while(tl<tr&&tl%B!=0) if(x>=A[tl++]) c++;
				while(tl<tr&&tr%B!=0) if(x>=A[--tr]) c++;
				while(tl<tr) {
					int b=tl/B;//編號爲b的桶
					c+=upper_bound(bucket[b],x)+1;
					tl+=B;
				}
				if(c>=k) {
					ub=mid;
				}else {
					lb=mid;
				}
			}
			out.println(num[ub]);
		}
		out.flush();
		out.close();
	}
	private static int upper_bound(ArrayList<Integer> arr, int x) {
		// 返回arr中不大於x的最右值對應的arr中下標
		int lb=-1;
		int ub=arr.size();
		while(ub-lb>1) {
			int mid=(lb+ub)/2;
			if(arr.get(mid)<=x) {
				lb=mid;
			}else {
				ub=mid;
			}
		}
		//System.out.println(lb+" "+x);
		return lb;
	}
}

發佈了76 篇原創文章 · 獲贊 3 · 訪問量 3948
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章