bzoj4900 [CTSC2017]密钥

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4900

【题解】

恭喜bzoj达到40页

考场由于傻逼基数排序写挂了而gg。

竟然忘了考试前一天复习了kd-tree里面有nth_element这种东西。。

那么看看样例,找找规律就发现排序的关键字是前缀和尽量小,其次位置尽量靠后(对于第三种是靠前)

直接上nth_element就行了。。

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 2e7 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, k, S, seed; 
int p[M], s[M];

struct pa {
    int s, pos;
    pa() {}
    pa(int s, int pos) : s(s), pos(pos) {}
}a[M];
int an = 0;

inline bool cmp1(pa a, pa b) {
    return a.s<b.s || (a.s==b.s && a.pos>b.pos);
} 
inline bool cmp2(pa a, pa b) {
    return a.s<b.s || (a.s==b.s && a.pos<b.pos);
} 

inline int randint() {
    seed = ((seed * 12321) ^ 9999) & 32767;
    return seed;
}

inline void input() {
    cin >> k >> seed >> S;
    int t = 0;
    n = k * 2 + 1;
    for(int i = 1; i <= n; ++i) {
        p[i] = (randint() >> 7) & 1;
        t += p[i];
    }
    int i = 1;
    while(t > k) {
        while(!p[i]) i++;
        p[i] = 0;
        t--;
    }
    while(t < k) {
        while(p[i]) i++;
        p[i] = 1;
        t++;
    }
}
 
int main() {
    input(); 
    for (int i=1; i<=n; ++i) {
        if(p[i]) p[i] = -1;
        else p[i] = 1; 
        s[i] = s[i-1] + p[i]; 
        if(p[i] == 1) {
            a[++an].s = s[i];
            a[an].pos = i;
        }
    }
    nth_element(a+1, a+1, a+an+1, cmp1);
    cout << a[1].pos << endl;
    nth_element(a+1, a+S+1, a+an+1, cmp1);
    cout << a[S+1].pos << endl;
    for(int i=1; i<=an; ++i) a[i].s = -a[i].s; 
    nth_element(a+1, a+S+1, a+an+1, cmp2);
    cout << a[S+1].pos << endl; 
    return 0;
}
View Code

 

posted @ 2017-05-25 19:46  Galaxies  阅读(334)  评论(0编辑  收藏  举报