具体就是那个维护一个 1500000 进制的两位数的做法,然后可以过样例但是前9个点WA了最后一个点甚至TLE。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <set>
#include <ctime>
#define int long long
using namespace std;
const int N = 1.5e6, base = 150000;
int t, n, tot, root, m, pe[N], pr[N];
typedef unsigned int ui ;
ui seed, last = 7;
ui randNum( ui& seed , ui last , const ui m){
seed = seed * 17 + last ; return seed % m + 1;
}
struct node{
int prob, pena, val, rk, ls, rs, sz;
}tr[N];
inline void write(int x) {
if(x < 10) {
putchar(x + 48);
return;
}
write( x / 10), write(x % 10);
return ;
}
int new_node(int pb, int pa) {
tr[++tot].prob = pb;
tr[tot].pena = base - pa;
tr[tot].val = base * pb + tr[tot].pena;
tr[tot].rk = rand();
tr[tot].sz = 1;
tr[tot].ls = tr[tot].rs = 0;
return tot;
}
void update(int k) {
tr[k].sz = tr[tr[k].ls].sz + tr[tr[k].rs].sz + 1;
return ;
}
void split(int k, int &a, int &b, int vl) {
if(!k) {
a = b = 0;
return ;
}
else if(tr[k].val <= vl) {
a = k;
split(tr[k].rs, tr[k].rs, b, vl);
}
else {
b = k;
split(tr[k].ls, a, tr[k].ls, vl);
}
update(k);
return ;
}
void merge(int &k, int a, int b) {
if(!a || !b) {
k = a + b;
return ;
}
else if(tr[a].rk >= tr[b].rk) {
k = a;
merge(tr[a].rs, tr[a].rs, b);
}
else {
k = b;
merge(tr[b].ls, a, tr[b].ls);
}
update(k);
return ;
}
void insert(int &k, int pb, int pa) {
int a = 0, b = 0, cur = new_node(pb, pa);
split(k, a, b, tr[cur].val);
merge(a, a, cur);
merge(k, a, b);
return ;
}
void del(int &k, int vl) {
int a = 0, b = 0, z = 0;
split(k, a, b, vl);
split(a, a, z, vl - 1);
merge(z, tr[z].ls, tr[z].rs);
merge(a, a, z);
merge(k, a, b);
return ;
}
int find_rank(int &k, int vl) {
int a = 0, b = 0, ret = 0;
split(k, a, b, vl);
ret = tr[b].sz;
merge(k, a, b);
return ret;
}
signed main() {
srand(time(0));
cin >> t;
while(t--) {
tot = root = 0;
cin >> m >> n >> seed;
for (int i = 1; i <= m; ++i) {
pe[i] = pr[i] = 0;
insert(root, pr[i], pe[i]);
}
for (int i = 1; i <= n; ++i) {
int u = randNum(seed, last, m), v = randNum(seed, last, m);
// cout << u << ' ' << v << ' ' << pr[u] * base + (base - pe[u]) << "\n";
del(root, pr[u] * base + (base - pe[u]));
pr[u]++, pe[u] += v;
insert(root, pr[u], pe[u]);
last = find_rank(root, tr[tot].val);
write(last);
puts("");
}
}
return 0;
}