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; }