分桶法和平方分割

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值