「TJOI2019」甲苯先生的滚榜

「TJOI2019」甲苯先生的滚榜

传送门
双关键字感觉不太好搞?直接压成一个 long long 就好了呗。
然后就是平衡树板子了。
参考代码:

#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
#define LL long long 
using namespace std;

template < class T > inline void read(T& s) {
	s = 0; int f = 0; char c = getchar();
	while ('0' > c || c > '9') f |= c == '-', c = getchar();
	while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
	s = f ? -s : s;
}

typedef unsigned int ui;
ui seed, last = 7;
inline ui randNum(const ui m) {
	seed = seed * 17 + last;
    return seed % m + 1;
}

const int _ = 1e6 + 5;

int T, n, m, rt, tot, siz[_], pri[_], ch[2][_]; LL val[_], w[_];

inline int Newnode(LL v)
{ return siz[++tot] = 1, pri[tot] = rand(), val[tot] = v, tot; }

inline void pushup(int p) { siz[p] = siz[ch[0][p]] + siz[ch[1][p]] + 1; }

inline int merge(int x, int y) {
	if (!x || !y) return x + y;
	if (pri[x] > pri[y])
		return ch[1][x] = merge(ch[1][x], y), pushup(x), x;
	else
		return ch[0][y] = merge(x, ch[0][y]), pushup(y), y;
}

inline void split(int p, LL v, int& x, int& y) {
	if (!p) { x = y = 0; return ; }
	if (val[p] <= v)
		return x = p, split(ch[1][p], v, ch[1][x], y), pushup(p);
	else
		return y = p, split(ch[0][p], v, x, ch[0][y]), pushup(p);
}

inline void erase(LL v) {
	int a, b, c;
	split(rt, v, a, c);
	split(a, v - 1, a, b);
	b = merge(ch[0][b], ch[1][b]);
	rt = merge(a, merge(b, c));
}

inline void insert(LL v) {
	int a, b;
	split(rt, v, a, b);
	rt = merge(a, merge(Newnode(v), b));
}

inline int rank(LL v) {
	int a, b, res;
	split(rt, v - 1, a, b);
	res = siz[a];
	rt = merge(a, b);
	return res;
}

inline void init() {
	rt = tot = 0;
	memset(w, 0, sizeof w);
	memset(ch, 0, sizeof ch);
	memset(siz, 0, sizeof siz);
	memset(pri, 0, sizeof pri);
	memset(val, 0, sizeof val);	
}

int main() {
	read(T);
	while (T--) {
		init();
		read(m), read(n), read(seed);
		for (rg int a, b; n--; ) {
			int ria = randNum(m), rib = randNum(m);
			erase(w[ria]);
			w[ria] += rib - 1500000;
			insert(w[ria]);
			last = rank(w[ria]);
			printf("%d\n", last);
		}
	}
	return 0;
}
posted @ 2020-01-23 22:08  Sangber  阅读(143)  评论(0编辑  收藏  举报