JZOJ3798临洮巨人

Posted stoorz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JZOJ3798临洮巨人相关的知识,希望对你有一定的参考价值。

题目

题目链接:https://jzoj.net/senior/#main/show/3798
技术图片

思路

半签到题我居然没有做出来(qwq)
(cnt[x][1/2/3])表示前(i)个子母中,字母(A,B,C)分别出现的次数。
那么一段区间([l,r])(A,B,C)数量相同,当且仅当(cnt[r][1]-cnt[l-1][1]=cnt[r][2]-cnt[l-1][2]=cnt[r][3]-cnt[l-1][3])
也就是需要分别满足

  • (cnt[r][1]-cnt[l-1][1]=cnt[r][2]-cnt[l-1][2] o cnt[r][1]-cnt[r][2]=cnt[l-1][1]-cnt[l-1][2])
  • (cnt[r][1]-cnt[l-1][1]=cnt[r][3]-cnt[l-1][3] o cnt[r][1]-cnt[r][3]=cnt[l-1][1]-cnt[l-1][3])

(p[i]=cnt[i][1]-cnt[i][2],q[i]=cnt[i][1]-cnt[i][3]),那么如果有两个位置(x,y),满足(p[x]=p[y])(q[x]=q[y])(x>y),那么([y+1,x])就是一个满足条件的区间。
我们考虑把二维压为一维,也就是令(T[x]=10^6 imes p[x]+q[x]),那么如果(T[x]=T[y])(y<x),那么([y+1,x])就是一个满足条件的区间。
所以就把每个位置的(T)求出来,排序然后指针扫描即可。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;

const int N=1000010;
int n,m,num,a[N];
ll ans,cnt[N][4],T[N];
char ch[N];

int main()
{
    scanf("%s",ch+1);
    n=strlen(ch+1);
    for (int i=1;i<=n;i++)
    {
        a[i]=ch[i]-'A'+1;
        cnt[i][1]=cnt[i-1][1]; cnt[i][2]=cnt[i-1][2]; cnt[i][3]=cnt[i-1][3];
        if (a[i]<=3) cnt[i][a[i]]++;
        T[i+1]=(cnt[i][1]-cnt[i][2])*1000000LL+cnt[i][1]-cnt[i][3];
    }
    n++;
    sort(T+1,T+1+n);
    for (int i=1,j=1;i<=n;i=j=j+1)
    {
        while (T[j+1]==T[i] && j<n) j++;
        ans+=1LL*(j-i+1)*(j-i);
    }
    printf("%lld",ans/2LL);
    return 0;
}

以上是关于JZOJ3798临洮巨人的主要内容,如果未能解决你的问题,请参考以下文章

机顶盒Hi3798m芯片怎么样?

洛谷 P3798 辉夜姬的十道难题

海思Hi3798MV310芯片处理器参数介绍

哥舒歌

Hi3798Mv100 U 盘卡刷教程(全新刷&&升级刷)

藏区架线 第二章