期望得分:100+100+20=220

实际得分:100+100+20=220

(好久没有期望==实际了 ,~\(≧▽≦)/~)

 

学大伟业 2017 国庆 Day1

学大伟业 2017 国庆 Day1

对于 a。。。。。。。。a

如果 第1个a 后面出现的第1个b~z 是右端点,且在第2个a之前,那么有贡献

如果 第2个a 前面出现的第1个b~z 是左端点,且在第1个a之后,那么有贡献

最后的贡献/2

 

#include<cstdio>
#include<cstring>

#define N 100001
 
using namespace std;

char s[N];

int LAST[26],last[N],pre[N][26],suf[N][26];
bool w[N],c[26];
 
int main()
{
    freopen("cross.in","r",stdin);
    freopen("cross.out","w",stdout);
    scanf("%s",s+1);
    int len=strlen(s+1),ans=0,ch;
    
    for(int i=1;i<=len;i++)
        for(int j=0;j<26;j++)
            if(s[i]-'a'==j) pre[i][j]=i;
            else pre[i][j]=pre[i-1][j];
    
    for(int i=0;i<26;i++) suf[len][i]=len+1;
    suf[len][s[len]-'a']=len;
    for(int i=len-1;i;i--)
        for(int j=0;j<26;j++)
            if(s[i]-'a'==j) suf[i][j]=i;
            else suf[i][j]=suf[i+1][j];
    
    for(int i=1;i<=len;i++)
    {
        ch=s[i]-'a';
        c[ch]^=1; w[i]=!c[ch];
        if(c[ch]) LAST[ch]=i;
        else last[i]=LAST[ch];
    }
    
    for(int i=1;i<=len;i++)
        if(w[i])
        {
            for(int j=0;j<26;j++)
                if(j!=s[i]-'a')
                {
                    if(suf[last[i]][j]<i && w[suf[last[i]][j]]) ans++;
                    if(pre[i][j]>last[i] && !w[pre[i][j]]) ans++;
                }
        }
        
    printf("%d",ans>>1);
}
View Code

相关文章: