BZOJ 3747: [POI2015]Kinoman

经典颜色问题推荐博文

https://www.cnblogs.com/tyner/p/11519506.html

https://www.cnblogs.com/tyner/p/11616770.html

https://www.cnblogs.com/tyner/p/11620894.html

题意:

https://www.lydsy.com/JudgeOnline/problem.php?id=3747
m 个不同颜色的点,每个点有个权值,现在由这 m 种颜色的点组成的长度为 n 的序列
求一个区间,这个区间内只出现一次的点的权值和最大

参考博客:http://hzwer.com/5715.html

分析

这种和颜色出现次数相关的题比较正常的想法就是枚举左端点,并计算出nxt[i] (与坐标 i 的颜色相同的下一个位置坐标

右移左端点的时候,处理“右移”这个操作对[l, nxt[l]-1] 以及 [nxt[l] , n] 这两个区间中答案的的影响。

注意可能有颜色不在序列中的情况

这题数据要开longlong

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
const int MAX = 1000000+99;

int n,m;
ll ans; 
int nxt[MAX], lst[MAX];
int f[MAX], w[MAX];
struct tree{
	ll add, mx;
}tr[MAX<<2];

void pushup(int o) {tr[o].mx = max(tr[o<<1].mx, tr[o<<1|1].mx);}
//void build(){}
void pushdown(int o) {
	if(0 == tr[o].add) return ;
	tr[o<<1].add += tr[o].add;
	tr[o<<1|1].add += tr[o].add;
	tr[o<<1].mx += tr[o].add;
	tr[o<<1|1].mx += tr[o].add;
	tr[o].add = 0;
}
void optadd(int o, int l, int r, int ql, int qr, int k) {
	if(ql<=l && r<=qr) {
		tr[o].add += k;
		tr[o].mx += k;
		return ;
	}
	int mid = (l+r)>>1;
	pushdown(o);
	if(ql <= mid) optadd(o<<1, l, mid, ql, qr, k);
	if(mid < qr) optadd(o<<1|1, mid+1, r, ql, qr, k);
	pushup(o);
}

int main() {
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n; i++) scanf("%d",&f[i]);
	for(int j = 1; j <= m; j++) scanf("%d",&w[j]);
	for(int i = n; i >= 1; i--) {
		nxt[i] = lst[f[i]];
		lst[f[i]] = i;
	}
	for(int i = 1; i <= m; i++) //先初始化左端点为 1 的情况(即处理每种颜色的第一个位置对答案的影响)
		if(lst[i]) {//注意判是否在序列中存在这个颜色(万一没有呢) 
			if(!nxt[lst[i]]) optadd(1, 1, n, lst[i], n, w[i]);//别越界了,时刻注意nxt,lst的含义 
			else optadd(1, 1, n, lst[i], nxt[lst[i]]-1, w[i]); 
		}
	int t;
	for(int i = 1; i <= n; i++) {
		ans = max(ans, tr[1].mx);//当左端点为 i 时,去的最大答案
		t = nxt[i];//以下表示左端点移到 i+1 后对答案的影响 
		if(t) {
			optadd(1, 1, n, i, t-1, -w[f[i]]);
			if(nxt[t]) optadd(1, 1, n, t, nxt[t]-1, w[f[i]]);
			else optadd(1, 1, n, t, n, w[f[i]]);
		} else optadd(1, 1, n, i, n, -w[f[i]]);
	}
	printf("%lld
",ans);
}
原文地址:https://www.cnblogs.com/tyner/p/11519506.html