CF786C Till I Collapse
Till I Collapse
题面翻译
将
输入格式
The first line of input contains a single integer
The second line contains
输出格式
In the first and only line of input print
样例 #1
样例输入 #1
5
1 3 4 3 3
样例输出 #1
4 2 1 1 1
样例 #2
样例输入 #2
8
1 5 7 8 1 7 6 1
样例输出 #2
8 4 3 2 1 1 1 1
提示
For the first sample testcase, some optimal ways of dividing army into squads for each
For the second testcase, some optimal ways of dividing army into squads for each
Solution
显然一个贪心的想法是每个选择的区间包含的颜色数量都尽可能多,这样总的段数就会很小。那么当每段区间内的颜色数量为
现在问题转化成为了已知左端点
延续那道题的做法,记录一个
原来的主席树是建一棵值域线段树,然后按照位置进行可持久化。而这道题为了能够在线段树上二分到
那么思路就显而易见了。先建出主席树,查询
代码实现上有一点细节需要注意。
完整代码
#include<bits/stdc++.h>
using namespace std;
namespace Hanx16qwq {
constexpr int _SIZE = 2e5;
int n;
int a[_SIZE + 5], pre[_SIZE + 5], last[_SIZE + 5];
int T[_SIZE + 5];
int ls[(_SIZE << 5) + 5], rs[(_SIZE << 5) + 5];
int sum[(_SIZE << 5) + 5], totNode, tail = 0;
#define mid ((l + r) >> 1)
int Build(int l, int r) {
int cur = ++totNode;
if (l < r)
ls[cur] = Build(l, mid),
rs[cur] = Build(mid + 1, r);
return cur;
}
int Update(int pre, int l, int r, int v) {
int cur = ++totNode;
ls[cur] = ls[pre], rs[cur] = rs[pre], sum[cur] = sum[pre] + 1;
if (l < r) {
if (v <= mid) ls[cur] = Update(ls[pre], l, mid, v);
else rs[cur] = Update(rs[pre], mid + 1, r, v);
}
return cur;
}
pair<int, int> Find(int u, int v, int l, int r, int a, int b, int k) {
if (l > b || r < a || k <= 0) return make_pair(0, 0);
if (l == r) {
return make_pair(l, sum[v] - sum[u]);
}
if (l >= a && r <= b) {
int res = sum[ls[v]] - sum[ls[u]];
if (k <= res) return make_pair(Find(ls[u], ls[v], l, mid, a, b, k).first, sum[v] - sum[u]);
else return make_pair(Find(rs[u], rs[v], mid + 1, r, a, b, k - res).first, sum[v] - sum[u]);
}
auto lres = Find(ls[u], ls[v], l, mid, a, b, k);
auto rres = Find(rs[u], rs[v], mid + 1, r, a, b, k - lres.second);
return make_pair(max(lres.first, rres.first), lres.second + rres.second);
}
int range[_SIZE + 5];
void main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n;
vector<pair<int, int>> all;
for (int i = 1; i <= n; i++) {
cin >> a[i];
pre[i] = last[a[i]];
last[a[i]] = i;
all.emplace_back(pre[i], i);
}
T[0] = Build(1, n + 1);
sort(all.begin(), all.end());
for (auto it : all) {
++tail;
T[tail] = Update(T[tail - 1], 1, n + 1, it.second);
range[it.first] = max(range[it.first], tail);
}
for (int i = 1; i <= n; i++)
range[i] = max(range[i], range[i - 1]);
for (int k = 1; k <= n; k++) {
int ans = 0;
for (int l = 1; l <= n;) {
int r = Find(T[0], T[range[l - 1]], 1, n + 1, l, n + 1, k + 1).first - 1;
ans++, l = r + 1;
}
cout << ans << ' ';
}
}
}
signed main() {
Hanx16qwq::main();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步