intさわだんのBlack History

刹那的レジェンドになりたい。

POJ 2104 K-th Number

例の平方分割で解ける問題

バケットのサイズを色々試してみた。

B = 1100 → TLE (>20000MS)
B = 1000 → 11735MS
B = 900 → 11782MS
B = 850 → 11829MS
B = 800 → 11157MS
B = 700 → 12235MS

結果B = 800が一番早い(?)

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

const int MN = 100000;
const int B = 800;

int n,m;
int a[MN];
int nums[MN];
vector<int> bucket[MN / B];
int main(){
	scanf("%d%d",&n,&m);
	for(int i = 0;i < n;i++){
		scanf("%d",&a[i]);
		bucket[i / B].push_back(a[i]);
		nums[i] = a[i];
	}
	sort(nums,nums+n);

	for(int i = 0;i < n / B;i++) sort(bucket[i].begin(),bucket[i].end());

	for(int i = 0;i < m;i++){
		int l,r,k;
		scanf("%d%d%d",&l,&r,&k);
		l--;
		int lb = -1,ub = n - 1;
		while(ub - lb > 1){
			int md = (lb + ub) / 2;
			int x = nums[md];
			int tl = l,tr = r,c = 0;

			while(tl < tr && tl % B != 0) if(a[tl++] <= x) c++;
			while(tl < tr && tr % B != 0) if(a[--tr] <= x) c++;

			while(tl < tr){
				int b = tl / B;
				c += upper_bound(bucket[b].begin(),bucket[b].end(),x) - bucket[b].begin();
				tl += B;
			}
			if(c >= k) ub = md;
			else lb = md;
		}
		printf("%d\n",nums[ub]);
	}
	return 0;
}