P6273 [eJOI2017] 魔法 题解

提供一个小常数 O(nklogn) 实现。

思路

根据题意,子串 S[l,r] 是有魔法的,当且仅当 kS,i=lr[Si=k] 都相等。

维护前缀和 sxk=i=1x[Si=k],则 S[l,r] 是有魔法的,当且仅当 kS,srksl1k 都相等。

srasl1a=srbsl1b 变形,得到 srasrb=sl1asl1b

任意选择一个 AS,则 S[l,r] 是有魔法的,当且仅当 kS,srksrA=sl1ksl1A

维护 vx={sxksxA|kS},则 S[l,r] 是有魔法的,当且仅当 vr=vl1

考虑对于每个 r,求出满足 vr=vl1l 的个数。

正序枚举 r,维护一个 map,计算出 vr 后,将答案加上 mapvr 的个数,再将 vr 加入 map

代码

一些细节:

  1. 注意到 vector 自带比较运算符,所以可以开 map<vector<int>, int>
  2. 注意到需要将字符作为 vector 的下标,所以需要离散化。
  3. 注意到 x[1,n],vx 只会用一次,所以可以动态更新 vx
  4. 注意到存在 l=1,l1=0 的情况,所以需要事先将全 0 集合加入 map
  5. 注意取模。注意答案开 long long

感觉其他题解都把代码写复杂了。

#include <bits/stdc++.h>
#define h(x) lower_bound(a, a + k, x) - a
using namespace std;
vector<int> v;map<vector<int>, int> m;
int n, k;long long q;char a[100050], s[100050];
int main()
{
    scanf("%d%s", &n, s);strcpy(a, s);sort(a, a + n);
    m[v = vector<int>(k = unique(a, a + n) - a, 0)] = 1;
    for (int i = 0; i < n; ++i)
    {
        if (s[i] != a[0]) ++v[h(s[i])];
        else {for (auto &x : v) --x;++v[0];}
        (q += m[v]++) %= 1000000007;
    }
    return printf("%lld", q), 0;
}

目前最优解 rk 1。

posted @   Jijidawang  阅读(35)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示