期望得分:60+ +0=60+

实际得分:30+56+0=86

时间规划极端不合理,T2忘了叉积计算,用解析几何算,还有的情况很难处理,浪费太多时间,最后gg

导致T3只剩50分钟,20分钟写完代码,没调出来

 

2017国庆 清北学堂 北京综合强化班 Day1

设sum[i][j] 表示字母j出现次数的前缀和

那么题目要求我们 最大化sum[r][x]-sum[l-1][x]-(sum[r][y]-sum[l-1][y])

如果枚举r,再枚举y,时间复杂度为O(n*26),是可以承受的

但此时还有l-1未知,能否O(1)找到l-1呢?

我们发现式子可以化为 :sum[r][x]-sum[r][y]-(sum[l-1][x]-sum[l-1][y])

这样减号两边形式相同

那就可以用前缀和来维护

所以设mi[i][j] 表示 当前 sum[i]-sum[j] 的最小值

在枚举r之前,l肯定已经计算过,所以sum的第一维可以不再mi中体现

那么ans=max(sum[r][x]-sum[r][y]-mi[x][y],sum[r][y]-sum[l][x]-mi[y][x])

 

小细节:

zhx的std中,

另外记录了当前每个字符的上一个出现的位置last[i],更新mi[i][j]的位置pos[i][j]

在更新答案的时候,是sum[r][x]-sum[r][y]-mi[x][y]-(pos[x][y]==last[i])

原因是因为 题目中要求 用来计算答案的 字母必须在所选区间出现过

std 每次在用sum更新mi时,不能保证用的这个字符出现过

还不明白的话 ,把std 的那句判等去掉,跑一遍数据:hhfffff

 

所以 我们仅需要在更新mi的时候,判断sum[]是否为真

便可以把这个特殊判断和last,pos 数组 去掉

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

#define N 1000001

int sum[N],mi[26][26];
char s[N];

int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    int n;
    scanf("%d",&n); scanf("%s",s+1);
    int ans=0;
    memset(mi,63,sizeof(63));
    for(int i=1;i<=n;i++)
    {
        int now=s[i]-'a';
        sum[now]++;
        for(int j=0;j<26;j++) 
            if(sum[j]) ans=max(ans,max(sum[now]-sum[j]-mi[now][j],sum[j]-sum[now]-mi[j][now]));
        for(int j=0;j<26;j++) 
        {
            if(sum[j] && sum[j]-sum[now]<mi[j][now]) mi[j][now]=sum[j]-sum[now];
            if(sum[j] && sum[now]-sum[j]<mi[now][j]) mi[now][j]=sum[now]-sum[j];
        }
    }
    printf("%d",ans);
}
View Code

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-11-13
  • 2021-12-11
  • 2022-12-23
  • 2021-11-30
  • 2021-08-24
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-06-01
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案