• 魔力


    ### Description

      数据范围:(n<=10^5)

      

    Solution

      脑抽选手选择回家种田qwq

      没啥难度的一题。。丢上来是为了记录一下场上的弱智操作。。

      首先想一下如果只有两种字符,那么出现次数我们可以求个差,然后从左往右扫,枚举右端点,如果当前前缀和之差的结果为(x),那么(ans)就应该加上前面的满足前缀和之差(=x)的位置的数量

    ​  字符比较多的情况下相邻的求差然后哈希压一下就好了

    ​  然而场上我的瓶颈在于。。认为这样并不能保证到每个字符都出现== 但实际上冷静一点想一下会发现由于查的是“前面的”满足条件的位置,所以可以保证到至少有一个字符出现了一次,而我们求的又是所有的字符出现次数相同的情况,那么自然不会出现有的字符没有出现这种情况==

    ​  然后我因为这个弱智操作写了一个线段树去拿字符集小的情况的部分分。。好结局qwq

      

    Code

    //Force是暴力
    //T2是十分弱智地写了个线段树去拿部分分
    //T3是正解
    //为自己的智商风暴哭泣qwq
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<map>
    #include<algorithm>
    #define ull unsigned long long
    using namespace std;
    const int N=1e5+10,C=52,MOD=1e9+7;
    char s[N];
    int Cnt[C],rec[C];
    int n,m,ans;
    int change(char ch){
        if ('a'<=ch&&ch<='z') return ch-'a';
        else return ch-'A'+26;
    }
    int plu(int x,int y){return (1LL*x+y)-(1LL*x+y>=MOD?MOD:0);}
    namespace Force{
        int cnt[N][C];
        bool check(int l,int r){
            int x,tmp=cnt[r][rec[1]]-cnt[l-1][rec[1]];
            if (tmp==0) return 0;
            for (int i=2;i<=rec[0];++i)
                if (cnt[r][rec[i]]-cnt[l-1][rec[i]]!=tmp) return 0;
            return 1;
        }
        void solve(){
            for (int i=1;i<=n;++i){
                for (int j=0;j<C;++j) cnt[i][j]=cnt[i-1][j];
                ++cnt[i][change(s[i])];
            }
            ans=0;
            for (int i=1;i<=n;++i){
                for (int j=i+rec[0]-1;j<=n;j+=rec[0])
                    if (check(i,j))
                        ans=plu(ans,1);
            }
        }
    }
    namespace Seg{
        const int N=::N*2*20;
        int ch[N][2],sum[N],rt[::N];
        int n,tot;
        void init(int _n){n=_n; tot=0;}
        int newnode(int pre){
            ++tot;
            ch[tot][0]=ch[pre][0]; ch[tot][1]=ch[pre][1];
            sum[tot]=sum[pre]; return tot;
        }
        void _modify(int pre,int &x,int d,int lx,int rx,int delta){
            x=newnode(pre);
            sum[x]+=delta;
            if (lx==rx) return;
            int mid=lx+rx>>1;
            if (d<=mid) _modify(ch[pre][0],ch[x][0],d,lx,mid,delta);
            else _modify(ch[pre][1],ch[x][1],d,mid+1,rx,delta);
        }
        void modify(int pre,int x,int d,int delta){++pre; ++x; _modify(rt[pre],rt[x],d,0,n,delta);}
        int _query(int x,int d,int lx,int rx){
            if (lx==rx) return sum[x];
            int mid=lx+rx>>1;
            if (d<=mid) return _query(ch[x][0],d,lx,mid);
            else return _query(ch[x][1],d,mid+1,rx);
        }
        int query(int x,int d){++x;return _query(rt[x],d,0,n);}
    }
    void debug(int x){
        for (int i=0;i<=n*2;++i) printf("%d ",Seg::query(x,i)); printf("
    ");
    }
    namespace T2{
        int sum[N*2],cnt[N][2];
        int loc[2],pre[N];
        void solve(){
            int c;
            loc[0]=0; loc[1]=0;
            for (int i=1;i<=n;++i){
                c=change(s[i])==rec[1];
                for (int j=0;j<2;++j) cnt[i][j]=cnt[i-1][j];
                ++cnt[i][c];
                pre[i]=loc[c^1];
                loc[c]=i;
            }
     
            Seg::init(2*n);
            Seg::modify(-1,0,0+n,1);
            ans=0;
            for (int i=1;i<=n;++i){
                if (pre[i])
                    ans=plu(ans,Seg::query(pre[i]-1,cnt[i][0]-cnt[i][1]+n));
                Seg::modify(i-1,i,cnt[i][0]-cnt[i][1]+n,1);
            }
        }
    }
    namespace T3{
        const int Hs=19260817;//just for debuging
        ull pw[C];
        map<ull,int> sum;
        int cnt[N][C];
        int loc[C],pre[N][C];
        ull get_val(int x){
            ull ret=0;
            int nxt;
            for (int i=1;i<::rec[0];++i){
                ret=ret*Hs+(cnt[x][::rec[i]]-cnt[x][::rec[i+1]]+n);
            }
            ret=ret*Hs+(cnt[x][::rec[rec[0]]]-cnt[x][::rec[1]]+n);
            return ret;
        }
        void solve(){
            int c,p;
            ull val;
            memset(loc,0,sizeof(loc));
            for (int i=1;i<=n;++i){
                c=change(s[i]);
                for (int j=1;j<=rec[0];++j) 
                    cnt[i][rec[j]]=cnt[i-1][rec[j]],pre[i][rec[j]]=pre[i-1][rec[j]];
                ++cnt[i][c];
                pre[i][c]=i;
            }
            val=get_val(0);
            sum[val]=1;
            for (int i=1;i<=n;++i){
                val=get_val(i);
                ans=plu(ans,sum[val]);
                sum[i]=sum[i-1];
                ++sum[val];
            }
        }
    }
    void prework(){
        int c;
        rec[0]=0;
        for (int i=1;i<=n;++i){
            c=change(s[i]);
            if (Cnt[c]==0) rec[++rec[0]]=c;
            ++Cnt[c];
        }
        sort(rec+1,rec+1+rec[0]);
    }
     
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("a.in","r",stdin);
    #endif
        scanf("%d",&n);
        scanf("%s",s+1);
        prework();
        if (rec[0]==2)
            T2::solve();
        else if (n<=2000)
            Force::solve();
        else
            T3::solve();
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    IOC注解开发与XML整合
    Spring的IOC注解开发入门2
    Spring的IOC注解开发入门1
    降维学习笔记
    决策树集成学习summary
    python shuffle
    为什么会突然难过
    保存为pickle
    gitlab被屏蔽问题
    selenium-历史(一)
  • 原文地址:https://www.cnblogs.com/yoyoball/p/10179589.html
Copyright © 2020-2023  润新知