[隊內測試Day10.26][P97]T1 字串+字首和
阿新 • • 發佈:2019-01-25
大意:
給定一字串,定義權值為串中出現次數最多字元 - 出現次數最少字元,求權值最大子串
字串長度 n <= 10^6,保證都由小寫字母組成
考完試悔的腸子都青了的題……
明明離正解那麼近了……
考場思路:
發現求區間l,r中字元a出現次數-字元b出現次數,用字首和可以表示為
即
而我們發現,
又因為掃描到某一位置時,作為最多字元更新目前最優答案的只可能是該位置上的字元
所以每一位置for一遍26個字元,尋找可能作為最小值的字元
還有問題……
雖然維護了 in(Sa−Sb)
但不一定該位置與當前位置組成的區間裡存在字元b
對此的處理方法:記錄b最後出現的位置和
因為注意到
所以
如果
%%%考場正解的summer && wyh
後來wyh講了更直觀的思路
“要suma和sumb的差值最大,就減去sumb比suma多的最多的區間”
ssssrO
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
char s[1000010];
int n;
int sum[30],mnum[30][30],mpos[30][30];
int last[1000010];
int ans;
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d",&n);
scanf("%s",s + 1);
memset (last,-1,sizeof(last));
for(int i = 1;i <= n;i ++){
int t = s[i] - 'a';
sum[t] ++;
last[t] = i;
for(int k = 0;k <= 25;k ++){
if(k == t)continue;
if(mnum[k][t] > sum[k] - sum[t])
mnum[k][t] = sum[k] - sum[t],mpos[k][t] = i;
}
for(int k = 0;k <= 25;k ++){
if(k == t || !sum[k])continue;
int tmp = sum[t] - sum[k] - mnum[t][k];
if(mpos[t][k] == last[k])tmp --;
ans = max(ans,tmp);
}
}
printf("%d",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
明明有思路的題放著不打,自己去T2找噁心……
但後來檢查考場程式碼思路確實凌亂……
Tips:
用適當的變數名代替表示式使程式碼更簡潔
對自己的思路有信心……