思路
赛时读错题了, 虽然说读对了不一定能做出来, 但是还是比较可惜
首先阐述一下题意, 对 \(S\) 数组进行插入和删除操作, 每次询问让你用 \(T\) 中的质数组合出 \(x\) , 然后将 \(S\) 中的数乘以 \(x\) 之后求最多的完全立方数个数
那么显然的, 我们对于每一个数, 都可以拆成质数之积, 那么显然的, 我们可以知道每个数需要什么质数才能凑成完全立方数
\(op = 1\)
如果这个数可能成为一个完全立方数, 我们记录这个数需要 \(T\) 中质数的个数, 这应该是一个 \(0, 1, 2\) 串串, 丢进去
时间复杂度 \(\mathcal{O} (M)\)
\(op = 2\)
扔出来
时间复杂度 \(\mathcal{O} (M)\)
\(op = 3\)
找最大, 结束
题解使用了 \(0, 1, 2 \ \rm{trie}\) , 但是被 \(\rm{klr}\) 的 \(\rm{pbds}\) 轻松冲过
还是稍微写一些 \(\rm{trie}\) , 补一下我的神秘基础
实现
代码
#include <bits/stdc++.h>
const int MAXM = 520;
const int MAXN = 5e6 + 1;
typedef long long ll;void write(__int128 x) {if (x < 0)putchar('-'), x = -x;if (x > 9)write(x / 10);putchar(x % 10 + '0');return;
}int M;
int prime[MAXM];
int Q;struct node {int App; // 串串的出现次数int son[3]; // 下一个节点int prime;__int128 x;
} Tree[MAXN];
int cnt = 1; // 0 为根节点bool check(ll rest)
{ll l = 1, r = 1000000;while (l <= r){ll mid = (l + r) >> 1;if (mid * mid * mid == rest)return 1;mid * mid * mid < rest ? l = mid + 1 : r = mid - 1;}return 0;
}std::vector<int> mstr;
std::set<int> leave;void ins() {ll num; scanf("%lld", &num);mstr.clear();for (int i = 1; i <= M; i++) {int cnt = 0; while (!(num % prime[i])) cnt++, num /= prime[i];mstr.push_back((3 - (cnt % 3)) % 3);}if (num != 1 && !check(num)) return;ll now = 0;__int128 nowx = 1;for (int i = 0; i < M; i++) {int ch = mstr[i];for (int j = 1; j <= ch; j++) nowx *= prime[i + 1];if (!Tree[now].son[ch]) Tree[now].son[ch] = cnt++;now = Tree[now].son[ch];Tree[now].prime = prime[i + 1];Tree[now].x = nowx;}Tree[now].App++;leave.insert(now);
}void del() {ll num; scanf("%lld", &num);mstr.clear();for (int i = 1; i <= M; i++) {int cnt = 0; while (!(num % prime[i])) cnt++, num /= prime[i];mstr.push_back((3 - (cnt % 3)) % 3);}if (num != 1 && !check(num)) return;ll now = 0;for (int i = 0; i < M; i++) {int ch = mstr[i];now = Tree[now].son[ch];}Tree[now].App--;
}__int128 ansx;
int ans;void solve()
{while (Q--) {int op; scanf("%d", &op);if (op == 1) ins();if (op == 2) del();if (op == 3) {ans = 0, ansx = 0;for (auto i : leave) {int now = i;if (Tree[now].App == 0) {continue;}__int128 x = Tree[now].x;if (ans == Tree[now].App) ansx = std::min(ansx, x);if (ans < Tree[now].App) ans = Tree[now].App, ansx = x;}write(ansx); printf("\n");}}
}signed main()
{scanf("%d", &M);for (int i = 1; i <= M; i++)scanf("%d", &prime[i]);scanf("%d", &Q);solve();return 0;
}
总结
注意读题
字符串插入删除, 字典树是最快的