猪猪的难题

猪猪的难题

逆向思维,对于一个字符ch,找到一个不含ch的最大子串,减去这个孙子子串数量,即为答案。
中间的完整片段可以预处理,然后只需要额外处理两端即可

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 1e18;

void solve() {
    int n, q; cin >> n >> q;
    string s; cin >> s; s = " " + s;
    
    vector<pair<int, int>> query(q);
    for(int i = 0; i < q; i ++) {
        cin >> query[i].first >> query[i].second;
    }

    vector<ll> ans(q + 1, 0);
    vector<int> cnt(n + 1);
    vector<ll> val(n + 1);
    vector<int> pos;
    
    for(int c = 0; c < 26; c ++) {
        char ch = c + 'a';

        pos.clear();
        for(int i = 1; i <= n; i ++) 
            if(s[i] == ch) pos.push_back(i);
        int k = pos.size();
        if(k == 0) {
            for(int j = 0; j < q; j ++) {
                auto [l, r] = query[j];
                ll len = r - l + 1;
                ans[j] += len * (len + 1) / 2;
            }
            continue;
        }

        cnt[0] = 0;
        for(int i = 1; i <= n; i ++) cnt[i] = cnt[i - 1] + (s[i] == ch);
        //计算前缀片段贡献
        ll f0 = pos[0];
        val[0] = (f0 - 1) * f0 / 2;
        for(int j = 1; j < k; j ++) {
            ll len = pos[j] - pos[j - 1] - 1;
            val[j] = val[j - 1] + len * (len + 1) / 2;
        }
        ll lenk = n - pos[k - 1];
        val[k] = val[k - 1] + lenk * (lenk + 1) / 2;

        for(int i = 0; i < q; i ++) {
            auto [l, r] = query[i];
            int left = cnt[l - 1], right = cnt[r];
            //中间没有ch,直接减去完全ch的贡献
            if(left == right) {
                ll len = r - l + 1;
                ans[i] += len * (len + 1) / 2;
            }
            else {
                int firl = pos[left], firh = pos[right - 1];
                ll mid = val[right - 1] - val[left];
                ll lenleft = firl - l, lenright = r - firh;
                ll valb = lenleft * (lenleft + 1) / 2 + lenright * (lenright + 1) / 2;
                ans[i] += valb + mid;
            }
        }
    }

    for(int i = 0; i < q; i ++) {
        auto [l, r] = query[i];
        ll len = r - l + 1;
        ll tol = len * (len + 1) * 13 - ans[i];
        cout << tol << " \n"[i == q - 1];
    }
}

int main() {  
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int _ = 1; cin >> _;
    while(_--) solve();
    return 0;
}
posted @ 2026-11-03 21:25  thenrify  阅读(2)  评论(0)    收藏  举报