HDU 6040

/*
HDU 6040 - Hints of sd0061 [ 第k小数查询,剪枝 ]
题意:
	给出随机数列 a[N] (N < 1e7)
	询问 b[M] (M < 100) ,对于每个询问输出第 b[i]+1小的数字
	满足对任意 i,j,k,若b[i] <= b[k] && b[j] <= b[k] 则一定有 b[i]+b[j] <= b[k]
分析:
	用 nth_element() 解决第k小数问题
	先将询问排序,可以从小到大或从大到小解决,就能每次不断缩小枚举区间
	根据询问的限制条件,选择从大到小解决,这样每次剪去的区间至少是一半
*/
#include <bits/stdc++.h>
using namespace std;
#define LL long long
unsigned x, y, z;
unsigned rng61() {
  unsigned t;
  x ^= x << 16;
  x ^= x >> 5;
  x ^= x << 1;
  t = x;
  x = y;
  y = z;
  z = t ^ x ^ y;
  return z;
}
const int N = 1e7+5;
unsigned a[N];
unsigned A, B, C, n, m;
void init()
{
    x = A, y = B, z = C;
    for (int i = 0; i < n; i++) a[i] = rng61();
}
struct Q{
    int id, x;
}q[105];
bool cmp(Q a, Q b) {
    return a.x < b.x;
}
unsigned ans[105];
int main()
{
    int tt = 0;
    while (~scanf("%u%u%u%u%u", &n, &m, &A, &B, &C))
    {
        for (int i = 0; i < m; i++)
        {
            scanf("%d", &q[i].x);
            q[i].id = i;
        }
        init();
        sort(q, q+m, cmp);
        q[m].x = n;
        for (int i = m-1; i >= 0; i--)
        {
            if (q[i].x == q[i+1].x) {
                ans[q[i].id] = ans[q[i+1].id]; continue;
            }
             nth_element(a, a+q[i].x, a+q[i+1].x);
             ans[q[i].id] = a[q[i].x];
        }
        printf("Case #%d:", ++tt);
        for (int i = 0; i < m; i++) printf(" %u", ans[i]);
        puts("");
    }
}

  

我自倾杯,君且随意
原文地址:https://www.cnblogs.com/nicetomeetu/p/7247416.html