2017多校一 1008题 hdu 6040 Hints of sd0061 排序 STL nth_element

34 篇文章 0 订阅
8 篇文章 0 订阅

题目链接


题意:

给定一串数字 a 与若干次询问 x(通过 b 数组给出),每次输出 a 中的 第 (x+1) 小数字


学了一招 nth_element,

nth_element is a partial sorting algorithm that rearranges elements in [first, last) such that:

  • The element pointed at by nth is changed to whatever element would occur in that position if [first, last) was sorted.
  • All of the elements before this new nth element are less than or equal to the elements after the new nth element.

——cppreference.com

// 说是效果近似线性0 0


因为 a 数组本身的特性,从大往小找是效率最高的。而且每次找完了大的,后面那段就可以直接扔掉,下次查找就以这次找到的位置作为结尾。

因此,考虑先将 b 数组从大到小排序。这里又学了一招,可以用 id[i] = i, 然后排序 id 数组,cmp 写作 

bool cmp(int u, int v) { return b[u] > b[v]; }

这样做起来感觉比结构体数组排序然后折腾啥的要清楚一点...(。


另一个注意点就是对于相同的询问可以直接继承上一次的答案(因为排过序后就靠在一起了),没必要再去查找。


Code:

#include <bits/stdc++.h>
#define maxn 10000010
unsigned x, y, z, rat[maxn], ans[maxn], A, B, C;
int n, m, b[110], id[110], kas;
using namespace std;
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;
}
bool cmp(int u, int v) { return b[u] > b[v]; }
void work() {
    x = A; y = B; z = C;
    for (int i = 0; i < n; ++i) rat[i] = rng61();
    for (int i = 0; i < m; ++i) { scanf("%d", &b[i]); id[i] = i; }
    sort(id, id + m, cmp);
    int en = n;
    for (int i = 0; i < m; ++i) {
        if (i > 0 && b[id[i]] == b[id[i - 1]]) {
            ans[id[i]] = ans[id[i - 1]];
            continue;
        }
        nth_element(rat, rat + b[id[i]], rat + en);
        ans[id[i]] = rat[b[id[i]]];
        en = b[id[i]];
    }
    printf("Case #%d: %u", ++kas, ans[0]);
    for (int i = 1; i < m; ++i) printf(" %u", ans[i]); printf("\n");
}
int main() {
    while (scanf("%d%d%u%u%u", &n, &m, &A, &B, &C) != EOF) work();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值