Difference bzoj-2213 Poi-2011
题目大意:已知一个长度为n的由小写字母组成的字符串,求其中连续的一段,满足该段中出现最多的字母出现的个数减去该段中出现最少的字母出现的个数最大。求这个个数。
注释:$1le nle 10^6$。
想法:“在线”的dp题。
状态:$dp[i][j]$表示在当前位置,字母$i$与字母$j$之间的最大差,$dp2[i][j]$表示出现次数的差。
这样的话就可以拿来更新答案了。
至于复杂度的的话,因为每次从$i$更新到$i+1$只会更改52个值,所以复杂度是$O(n)$的。
最后,附上丑陋的代码... ...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define K 50 using namespace std; int sum[K],f[K][K],g[K][K],c[K][K],h[K][K],d[K][K],ans; char str[1000010]; void update(int a , int b) { if(c[a][b] < sum[b]) ans = max(ans , f[a][b] - g[a][b]); else if(d[a][b] < sum[b]) ans = max(ans , f[a][b] - h[a][b]); if(f[a][b] < g[a][b]) { if(c[a][b] < sum[b]) h[a][b] = g[a][b] , d[a][b] = c[a][b]; g[a][b] = f[a][b] , c[a][b] = sum[b]; } else if(c[a][b] < sum[b] && f[a][b] < h[a][b]) h[a][b] = f[a][b] , d[a][b] = sum[b]; } int main() { int n,t; scanf("%d%s" , &n , str + 1); for(int i=1;i<=n;i++) { t=str[i]-'a'; sum[t]++; for(int j=0;j<K;j++) if(t != j) f[t][j]++,update(t,j),f[j][t]--,update(j,t); } printf("%d ",ans); return 0; }
小结:挺好的题(好像是lzh的考试题)。