1 条题解
-
0
自动搬运
来自洛谷,原作者为

Iniaugoty
我一定会进盐中校队!!!!!11111搬运于
2025-08-24 23:05:06,当前版本为作者最后更新于2024-10-13 19:18:27,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P11190 「KDOI-10」反回文串
两个特殊性质已经把做法塞你嘴里了。
考虑 A 性质。
如果 ,这时是可以将颜色不同的两两配对上的。考虑将原序列重排,使颜色相同的放在一起,此时把 分进一个子序列是可行的(经典思路,因为不存在绝对众数,而颜色相同的是连续的,所以他们颜色不同)。答案最优为 。
如果 ,把多出来的 加进 里面就行了,原因同上。答案最优为 。
考虑 B 性质。
这意味着至少有一种颜色数量达到了 ,称这种颜色为 X,另一种颜色为 Y。
显然的是分出来的每个子序列都至少有一个 Y,所以所有颜色相同时无解。
当 Y 只有一个时,只能将所有的分在一起。如果此时 并且 (即正中心)为 Y 时,它本身就是一个形如
...XXXYXXX...的回文,无解;否则必然不回文,答案为 。当 Y 有两个时。设第一个 Y 的位置为 ,最后一个 Y 的位置为 。把 中的 X 分给 , 中的 X 分给 。如果分下来有个 Y 没有 X 的话注意从另一个里面分过来一个。这样会得到形如
YXXX...和...XXXY的东西。答案最优为 。当 Y 更多时,延续上面的思路。 之间的 Y 没有 X,从 或 的里面分过来一个就行了。这样会得到形如
YXXX...,...XXXY和一大堆XY,YX。答案最优为 Y 的数量。考虑正解。
不存在绝对众数时,用 A 性质做法;否则将绝对众数当成 X,其他颜色当成 Y,用 B 性质做法。
就做完了,时间复杂度是线性,根据实现可能会带点别的什么东西。
#include <bits/stdc++.h> #define F(i, a, b) for(int i = (a); i <= (b); ++i) #define dF(i, a, b) for(int i = (a); i >= (b); --i) using namespace std; typedef long long LL; typedef unsigned long long ull; typedef unsigned uint; typedef pair<int, int> pii; const int N = 1e5 + 5; int n, t[140], zyq; char s[N]; int p[N]; vector<int> qu[140]; int cnt; vector<int> ans[N]; void mian() { cin >> n, zyq = -1, cnt = 0; F(i, 'a', 'z') t[i] = 0, qu[i].clear(); F(i, 1, n) cin >> s[i], ++t[s[i]]; F(i, 'a', 'z') if (t[i] >= n + 1 >> 1) zyq = i; if (zyq < 0) { F(i, 1, n) qu[s[i]].push_back(i); cnt = n >> 1; int tot = 0; F(i, 'a', 'z') for (auto it : qu[i]) p[++tot] = it; F(i, 1, n >> 1) ans[i].push_back(p[i]), ans[i].push_back(p[i + (n >> 1)]); if (n & 1) ans[1].push_back(p[n]); } else { if (t[zyq] == n) { return cout << "Shuiniao\n", void(); } if (t[zyq] == n - 1) { if ((n & 1) && s[n + 1 >> 1] != zyq) { return cout << "Shuiniao\n", void(); } cout << "Huoyu\n1\n" << n << " "; F(i, 1, n) cout << i << " "; return cout << "\n", void(); } int l, r; cnt = 2; F(i, 1, n) if (s[i] != zyq) { l = i; break; } dF(i, n, 1) if (s[i] != zyq) { r = i; break; } ans[1].push_back(l), ans[2].push_back(r); F(i, l + 1, n) if (s[i] == zyq) ans[1].push_back(i); F(i, 1, l - 1) if (s[i] == zyq) ans[2].push_back(i); F(i, l + 1, r - 1) if (s[i] != zyq) ans[++cnt].push_back(i); F(i, 1, cnt) if (ans[i].size() < 2) if (ans[1].size() > 2) ans[i].push_back(ans[1].back()), ans[1].pop_back(); else ans[i].push_back(ans[2].back()), ans[2].pop_back(); } cout << "Huoyu\n" << cnt << "\n"; F(i, 1, cnt) { cout << ans[i].size() << " "; sort(ans[i].begin(), ans[i].end()); for (auto it : ans[i]) cout << it << " "; cout << "\n", ans[i].clear(); } } int main() { // freopen("zyq.in", "r", stdin); // freopen("zyq.out", "w", stdout); ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); int c, _; cin >> c >> _; while (_--) mian(); return 0; }
- 1
信息
- ID
- 10677
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者