洛谷 3519 bzoj 2213 Difference
聯考考試考到了這個題,隨機化40分,現在來秒掉它吧。
?
題意:
給一個字符串,求其中的一段,使得出現次數最多的字符與出現次數最少的字符的出現次數之差最大。
輸入輸出樣例
輸入樣例#1:?復制10 aabbaaabab輸出樣例#1:?復制
3
?
我們定義$cnt[i][j]$表示區間$[1,i]$中,j出現的次數,
定義字符a,b(非字符a,b),a為出現最多的字符,b為出現最少的字符。
我們利用前綴和統計每一個字符出現的次數。
那么對于一個區間$[i,j]$,字符a出現的次數為$cnt[j][a]-cnt[i][a]$,字符b出現的次數為$cnt[j][b]-cnt[i][b]$,我們枚舉每一個字符的配對情況。
對于26個字符$$ans=max \{ ans,(cnt[j][a]-cnt[i][a])-(cnt[j][b]-cnt[i][b]) \}$$。
這樣枚舉時間復雜度$O(n^2 \times 26 \times 26)$,還可以啦。
現在我們來優化一下上邊的過程。
$$(cnt[j][a]-cnt[i][a])-cnt[j][b]-(cnt[i][b])$$
可以變為
$$(cnt[j][a]-cnt[j][b])-(cnt[i][a]-cnt[i][b])$$
對于算式的前半邊O(n \times 26)枚舉,我們來優化一下后半邊。
對于后邊的式子,求得為j以前$cnt[i][a]-cnt[i][b]$的最小值,然而j是怎么過來的,到了j必然前邊的數都有經過,所以我們在枚舉是維護一個$cnt[i][a]-cnt[i][b]$的最小值即可(代碼中用到minv數組)。
代碼中有p[i][j]數組表示更新字符i和字符j差的最小值的位置。
總的時間復雜度$O(n \times 26)$
?
#include<complex> #include<cstdio> using namespace std; const int N=1e6+7,M=27; int n,ans; int last[M],num[M],p[M][M],minv[M][M]; /* last表示字符最后出現的位置,num表示字符出現的次數。 p數組表示更新維護最小值的位置,minv表示維護的最小值。*/ char s[N]; int main() { // freopen("B.in","r",stdin); // freopen("B.out","w",stdout);scanf("%d%s",&n,s+1);for(int i=1; i<=n; i++){int c=s[i]-'a';num[c]++;last[c]=i;for(int j=0; j<26; j++)if(j!=c && num[j])ans=max(ans,max(num[c]-num[j]-minv[c][j]-(last[j]==p[c][j]),num[j]-num[c]-minv[j][c]-(last[c]==p[j][c])));/*最后出現的位置與最小值更新的位置相等,那么在我們判斷的區間里,不會出現j,對于這段區間-j,就等于只是選定區間內c出現的次數,這是不符合條件的,那么要讓他更大,再向左選一個不同的字符那么tot[u]-1一定是最優的。*/for(int j=0; j<26; j++)if(num[j]-num[c]<minv[j][c]){minv[j][c]=num[j]-num[c];p[j][c]=i;}//更新最小值。 }printf("%d\n",ans); // fclose(stdin);fclose(stdout);return 0; }
?
轉載于:https://www.cnblogs.com/rmy020718/p/9615482.html
總結
以上是生活随笔為你收集整理的洛谷 3519 bzoj 2213 Difference的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国庆去泰国穿什么衣服,国庆去泰国热吗
- 下一篇: RoadMap