BZOJ 2213: [Poi2011]Difference (DP)

题意

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

题解

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

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

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

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\n", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值