zoukankan      html  css  js  c++  java
  • BZOJ 2213: [Poi2011]Difference (DP)

    题意

    求一段区间内最大字母出现次数-最小字母出现次数的最大值。

    题解

    考虑f[i][j]f[i][j]代表当前字符ii减去字符jj的个数…

    那么答案为maxf[r][i][j]f[l1][i][j]max f[r][i][j]−f[l−1][i][j]

    当右端点从xx变为x+1x+1的时候最多改变5252个值,所以暴力更新,同时维护最小的f[i][j]f[i][j]和次小的f[i][j]f[i][j]。注意求答案的时候要保证这段区间内最小字母出现次数不为00

    CODE

    #pragma GCC optimize ("O2")
    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1000005;
    const int MAXM = 30;
    int n, ans, tot[MAXM], cnt[MAXM][MAXM], Min[2][MAXM][MAXM], val[2][MAXM][MAXM];
    char s[MAXN];
    inline void upd(int i, int j) {
    	if(tot[j] != val[0][i][j]) ans = max(ans, cnt[i][j] - Min[0][i][j]);
    	else if(tot[j] != val[1][i][j]) ans = max(ans, cnt[i][j] - Min[1][i][j]);
    	
    	if(cnt[i][j] < Min[0][i][j] && val[0][i][j] != tot[j]) {
    		Min[1][i][j] = Min[0][i][j], val[1][i][j] = val[0][i][j];
    		Min[0][i][j] = cnt[i][j], val[0][i][j] = tot[j];
    	}
    	else if(cnt[i][j] < Min[0][i][j]) {
    		Min[0][i][j] = cnt[i][j];
    	}
    	else if(cnt[i][j] < Min[1][i][j] && val[0][i][j] != tot[j]) {
    		Min[1][i][j] = cnt[i][j], val[1][i][j] = tot[j];
    	}
    }
    int main () {
        scanf("%d%s", &n, s);
    	for(int i = 0, k, j; i < n; ++i)
    		for(++tot[k = s[i]-'a'], j = 0; j < 26; ++j)
    			if(j != k) {
    				++cnt[k][j], upd(k, j);
    				--cnt[j][k], upd(j, k);
    			}
    	printf("%d
    ", ans);
    }
    
  • 相关阅读:
    一些PC小软件/工具/神器备份
    三角函数与反三角函数
    常用网站整理(书签整理)
    谷歌和谷歌学术镜像网站
    微擎系统jssdk系统快速签名变量
    phpexcel 导入超过26列时的解决方案
    js循环对象,(多层数组)
    CentOS 6 下无法wget https链接的解决方法
    centos6 7 yum安装mongodb 3.6
    yum except KeyboardInterrupt, e: 错误
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039233.html
Copyright © 2011-2022 走看看