分桶法和平方分割

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//超时= =
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;
	}
}

发布了73 篇原创文章 · 获赞 3 · 访问量 3503

猜你喜欢

转载自blog.csdn.net/qq_42021845/article/details/103324603