(好像题目都比较水)
算法:DP,矩阵
显然DP。设字符集大小为size
,直接搞显然\(\mathcal O(size^2n)\)。用矩阵加速,复杂度\(\mathcal O(size^3\log_2n)\)。
算法:平衡树或线段树
板子题。直接上平衡树模拟,复杂度\(\mathcal O(n\log n)\)。或者常数小的,用线段树配合线段树(有点像树套树,但不一样),分别维护第一关键字和第二关键字,第一关键字可以用树状数组,第二关键字用动态开点线段树,复杂度同上。
#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = a, i##end = b; i <= i##end; ++i)
const int maxn = 100000 + 5, maxm = 1000000 + 5, size = 1500000 + 5;
int n, m, lastans = 7;
unsigned int seed;
int randNum() {
seed = seed * 17 + lastans;
return seed % n + 1;
}
namespace SGT {
struct Node {
int l, r, v;
Node() : l(0), r(0), v(0) {};
} node[maxm*21];
#define ls node[o].l
#define rs node[o].r
int pt;
void clear() { pt = 0; }
void modify(int &o, int l, int r, int p, int v) {
if (!o) node[o = ++pt] = Node();
node[o].v += v;
if (l == r) return;
int mid = l+r>>1;
if (p <= mid) modify(ls, l, mid, p, v);
else modify(rs, mid+1, r, p, v);
}
int query(int o, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) return node[o].v;
int mid = l+r>>1, res = 0;
if (ql <= mid) res += query(ls, l, mid, ql, qr);
if (mid < qr) res += query(rs, mid+1, r, ql, qr);
return res;
}
}
int rt[maxm];
namespace BIT {
#define lb(x) (x & (-x))
int C[maxm];
void clear() { memset(C, 0, sizeof C); }
void modify(int i, int v) {
for (; i <= m+1; i += lb(i)) C[i] += v;
}
int query(int i) {
int res = 0;
for (; i; i -= lb(i)) res += C[i];
return res;
}
}
int ac[maxn], tme[maxn];
void modify(int x, int v) {
BIT::modify(ac[x]+1, v);
SGT::modify(rt[ac[x]], 0, size, tme[x], v);
}
int query(int x) {
return BIT::query(m+1) - BIT::query(ac[x]+1) + (tme[x] ? SGT::query(rt[ac[x]], 0, size, 0, tme[x]-1) : 0);
}
int main() {
for (int T = read(); T; T--) {
n = read(), m = read(), seed = read();
SGT::clear(); BIT::clear();
rep(i, 0, m) rt[i] = 0;
rep(i, 1, n) ac[i] = tme[i] = 0, modify(i, 1);
rep(i, 1, m) {
int x = randNum(), y = randNum();
modify(x, -1); ac[x]++; tme[x] += y; modify(x, 1);
printf("%d\n", lastans = query(x));
}
}
return 0;
}
算法:容斥+DP+NTT优化
(坑坑坑)
原文:https://www.cnblogs.com/ac-evil/p/12572099.html