6638. 【GDOI2020.5.16模拟】Seat (队列)
Description:
https://gmoj.net/senior/#main/show/6638
题解:
因为数据太水了,所以暴力用map维护就能过这题了。
考虑一个更加靠谱的做法,类似于《蚯蚓》,用两个队列维护,一个队列是一开始的排好序加进去。
另一个队列就是新产生的数的队列。
不难发现,对于两个数\(x>y\),x产生的数一定大于等于y产生的数,所以第二条队列会一直是有序的。
每次从两个队列取出最大即可,注意最大有多个要全部去掉。
时间复杂度:\(O(n*log~V)\)
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int N = 1e6 + 5;
int n;
ll a[N], A, B, C, mo;
int m;
struct nod {
int i; ll x;
} b[N];
int ans[N];
int cmpb(nod a, nod b) {
return a.x < b.x;
}
int cmpa(ll x, ll y) {
return x > y;
}
struct P {
int x; ll y;
P(int _x = 0, ll _y = 0) {
x = _x, y = _y;
}
};
queue<P> d1, d2;
int main() {
freopen("seat.in", "r", stdin);
freopen("seat.out", "w", stdout);
scanf("%d", &n);
scanf("%lld %lld %lld %lld %lld", &a[1], &A, &B, &C, &mo);
fo(i, 2, n) {
a[i] = (a[i - 1] * a[i - 1] % mo * A + B * a[i - 1] + C) % mo + 1;
}
scanf("%d", &m);
fo(i, 1, m) {
scanf("%lld", &b[i].x);
b[i].i = i;
}
sort(b + 1, b + m + 1, cmpb);
sort(a + 1, a + n + 1, cmpa);
fo(i, 1, n) d1.push(P(a[i], 1));
ll sum = 0; int l = 0;
while(d1.size() || d2.size()) {
int x = 0;
if(d1.size()) x = max(x, d1.front().x);
if(d2.size()) x = max(x, d2.front().x);
ll y = 0;
while(d1.size() && d1.front().x == x) {
y += d1.front().y;
d1.pop();
}
while(d2.size() && d2.front().x == x) {
y += d2.front().y;
d2.pop();
}
if(x > 1) d2.push(P(x / 2, y));
if(x > 2) d2.push(P((x - 1) / 2, y));
sum += y;
while(l < m && b[l + 1].x <= sum)
l ++, ans[b[l].i] = x;
}
fo(i, 1, m) pp("%d\n", ans[i]);
}
转载注意标注出处:
转自Cold_Chair的博客+原博客地址