BZOJ5509: [Tjoi2019]甲苯先生的滚榜

题解

开n个平衡树对每个AC数维护罚时,然后不同AC数用树状数组维护即可。
其实挺好写的...就是评测的时候评的巨久...

#include 
using namespace std;
 
typedef long long ll;
const int N = 1000010;
 
int T, n, m, cnt[N], tim[N];
 
namespace Rand {
typedef unsigned int ui;
ui seed;
ui randNum(ui& seed, ui last, const ui m) {
    seed = seed * 17 + last;
    return seed % m + 1;
}
}
namespace fhqtreap {
int root[N], tot;
struct treap {int lc, rc, val, rnd, siz;} t[N<<2];
void clear() {memset(root, 0, sizeof(root)); tot = 0;}
void up(int rt) {t[rt].siz = t[t[rt].lc].siz + t[t[rt].rc].siz + 1;}
int build(int val) {
    t[++tot] = (treap) {0, 0, val, rand()<<15|rand(), 1};
    return tot;
}
void split(int rt, int &l, int &r, int c) {
    if(!rt) l = r = 0;
    else if(t[rt].val <= c) split(t[l = rt].rc, t[rt].rc, r, c), up(rt);
    else split(t[r = rt].lc, l, t[rt].lc, c), up(rt);
}
void merge(int &rt, int l, int r) {
    if(!l || !r) rt = l + r;
    else if(t[l].rnd < t[r].rnd) rt = l, merge(t[rt].rc, t[rt].rc, r), up(rt);
    else rt = r, merge(t[rt].lc, l, t[rt].lc), up(rt);
}
void insert(int id, int val) {
    int x, y, z = build(val); 
    split(root[id], x, y, val);
    merge(x, x, z); merge(root[id], x, y);
}
void Del(int id, int val) {
    int x, y, z;
    split(root[id], x, y, val);
    split(x, x, z, val - 1);
    merge(z, t[z].lc, t[z].rc);
    merge(x, x, z); merge(root[id], x, y);
}
int rnk(int rt, int val) {
    if(!rt) return 0;
    if(t[rt].val >= val) return rnk(t[rt].lc, val);
    return rnk(t[rt].rc, val) + t[t[rt].lc].siz + 1;
}
}
namespace BIT {
int c[N];
#define lowbit(i) (i & -i)
void clear() {memset(c, 0, sizeof(c));}
void add(int x, int v) {for(int i = x; i <= n; i += lowbit(i)) c[i] += v;}   
int query(int x) {int ans = 0; for(int i = x; i; i -= lowbit(i)) ans += c[i]; return ans;}
}
 
int main() {
    int ans = 7; scanf("%d", &T); while(T--) {
    fhqtreap::clear(); BIT::clear(); 
    memset(cnt, 0, sizeof(cnt)); memset(tim, 0, sizeof(tim));
    scanf("%d%d%u", &m, &n, &Rand::seed);
    for(int i = 1; i <= n; ++i) {
        int Ria = Rand::randNum(Rand::seed, ans, m);
        int Rib = Rand::randNum(Rand::seed, ans, m);
        if(cnt[Ria]) {
            fhqtreap::Del(cnt[Ria], tim[Ria]);
            BIT::add(cnt[Ria], -1);
        }
        tim[Ria] += Rib; ++cnt[Ria];
        BIT::add(cnt[Ria], 1);
        fhqtreap::insert(cnt[Ria], tim[Ria]);
        ans = fhqtreap::rnk(fhqtreap::root[cnt[Ria]], tim[Ria]) + BIT::query(n) - BIT::query(cnt[Ria]);
        printf("%d\n", ans);
    }}
    return 0;
}

你可能感兴趣的:(BZOJ5509: [Tjoi2019]甲苯先生的滚榜)