1 条题解

  • 0
    @ 2025-8-24 23:05:06

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Iniaugoty
    我一定会进盐中校队!!!!!11111

    搬运于2025-08-24 23:05:06,当前版本为作者最后更新于2024-10-13 19:18:27,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    P11190 「KDOI-10」反回文串

    两个特殊性质已经把做法塞你嘴里了。

    考虑 A 性质。

    如果 2n2 \mid n,这时是可以将颜色不同的两两配对上的。考虑将原序列重排,使颜色相同的放在一起,此时把 (i,i+n2)(i, i + \frac n 2) 分进一个子序列是可行的(经典思路,因为不存在绝对众数,而颜色相同的是连续的,所以他们颜色不同)。答案最优为 n2\frac n 2

    如果 2n2 \nmid n,把多出来的 nn 加进 (1,1+n2)(1, 1 + \lfloor \frac n 2 \rfloor) 里面就行了,原因同上。答案最优为 n2\lfloor \frac n 2 \rfloor

    考虑 B 性质。

    这意味着至少有一种颜色数量达到了 n2\lceil \frac n 2 \rceil,称这种颜色为 X,另一种颜色为 Y。

    显然的是分出来的每个子序列都至少有一个 Y,所以所有颜色相同时无解。

    当 Y 只有一个时,只能将所有的分在一起。如果此时 2n2 \nmid n 并且 sn2s _ {\lfloor \frac n 2 \rfloor}(即正中心)为 Y 时,它本身就是一个形如 ...XXXYXXX... 的回文,无解;否则必然不回文,答案为 11

    当 Y 有两个时。设第一个 Y 的位置为 ll,最后一个 Y 的位置为 rr。把 [l+1,n][l + 1, n] 中的 X 分给 ll[1,l1][1, l - 1] 中的 X 分给 rr。如果分下来有个 Y 没有 X 的话注意从另一个里面分过来一个。这样会得到形如 YXXX......XXXY 的东西。答案最优为 22

    当 Y 更多时,延续上面的思路。[l+1,r1][l + 1, r - 1] 之间的 Y 没有 X,从 llrr 的里面分过来一个就行了。这样会得到形如 YXXX......XXXY 和一大堆 XYYX。答案最优为 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
    上传者