其他分享
首页 > 其他分享> > CF1408H Rainbow Triples

CF1408H Rainbow Triples

作者:互联网

CF1408H Rainbow Triples

devinwang:检验你们学习成果
我:我题解都看不懂

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mkp make_pair
#define pb push_back
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define ls(x) ((x) << 1)
#define rs(x) ((x) << 1 | 1)
#define fi first
#define se second
const int N = 5e5 + 10, inf = 0x3f3f3f3f;
int n;
int lz[N << 2], tr[N << 2], num[N], pre[N], suf[N], lx[N], rx[N];
bool vis[N];
void pushdown(int rt) {
	if(lz[rt]) {
		lz[ls(rt)] += lz[rt]; tr[ls(rt)] += lz[rt];
		lz[rs(rt)] += lz[rt]; tr[rs(rt)] += lz[rt];
		lz[rt] = 0;
	}
	return;
}
void pushup(int rt) {
	tr[rt] = min(tr[ls(rt)], tr[rs(rt)]);
}
void build(int rt, int l, int r) {
	if(l == r) {
		return tr[rt] = l, void();
	}
	pushdown(rt);
	int mid = (l + r) / 2;
	build(ls(rt), l, mid);
	build(rs(rt), mid + 1, r);
	pushup(rt);
}
void update(int rt, int l, int r, int L, int R) {
	if(L <= l && r <= R) {
		lz[rt]--; tr[rt]--;
		return;
	}
	pushdown(rt);
	int mid = (l + r) / 2;
	if(L <= mid) update(ls(rt), l, mid, L, R);
	if(R > mid) update(rs(rt), mid + 1, r, L, R);
	pushup(rt);
}
void clear() {
	for(int i = 1; i <= n; i++)
		vis[i] = lx[i] = rx[i] = 0;
	for(int i = 1; i <= (n << 2); i++)
		lz[i] = 0, tr[i] = inf;
}
void solve() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++)
		scanf("%d", &num[i]), vis[num[i]] = 1;
	pre[0] = suf[n + 1] = 0;
	for(int i = 1; i <= n; i++)
		pre[i] = pre[i - 1] + !num[i];
	for(int i = n; i >= 1; i--)
		suf[i] = suf[i + 1] + !num[i];
	
	int cntl = pre[n] / 2, cntr = pre[n] - cntl;
	build(1, 0, cntr);
	for(int i = 1; i <= n; i++) {
		if(pre[i] > cntl) break;
		lx[num[i]] = i;
	}
	for(int i = n; i >= 1; i--) {
		rx[num[i]] = i;
		if(suf[i] >= cntr) break; 
	}
	
	int col = 0;
	for(int i = 1; i <= n; i++)
		if(vis[i]) col++;
	int ans = min(pre[n] / 2, col);
	
	for(int i = 1; i <= n; i++) 
		if(vis[i] && !lx[i]) {
			update(1, 0, cntr, suf[rx[i]], cntr);
			ans = min(ans, col + tr[1]);
		}
	
	for(int i = 1; i <= n; i++) {
		if(pre[i] > cntl) break;
		int u = num[i];
		if(u && lx[u] == i) {
			if(!rx[u]) update(1, 0, cntr, 0, cntr);
			else update(1, 0, cntr, suf[rx[u]], cntr);
			ans = min(ans, col + tr[1] + pre[i]);
		}
	}
	printf("%d\n", ans);
	
	clear();
	return;
}
int main(){
	memset(tr, 0x3f, sizeof(tr));
	int T; scanf("%d", &T);
	while(T--) solve();
	return 0;
}
/*
8
1
1
2
0 0
3
0 1 0
6
0 0 1 2 0 0
6
0 1 0 0 1 0
6
0 1 3 2 0 0
6
0 0 0 0 5 0
12
0 1 0 2 2 2 0 0 3 3 4 0
*/

标签:Rainbow,cntl,颜色,int,ans,cntr,CF1408H,Triples,define
来源: https://www.cnblogs.com/zdsrs060330/p/15832377.html