[JZOJ 5811] 简单的填数

题意:自己搜吧。。。
思路:
记二元组\((x,l)\)表示当前为\(x\)且之前有\(l\)个连续数与\(x\)相同。
并且维护up和low数组表示取到最大/最小值时,连续序列的长度。
正一遍,反一遍,搞定。
我排序手抖达成\(a.r and b.r\),调了1小时...

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200010;
inline int read () {
	int q=0,f=1;char ch = getchar();
	while(!isdigit(ch)){
		if(ch=='-')f=-1;ch=getchar();
	}
	while(isdigit(ch)){
		q=q*10+ch-'0';ch=getchar();
	}
	return q*f;
}
struct node {
	int l,r;
}up[maxn],low[maxn];

node Max(node a,node b) {
	if(a.l > b.l||(a.l == b.l && a.r > b.r)) return a;
	else return b;
}

node Min(node a,node b) {
	if(a.l > b.l||(a.l == b.l && a.r > b.r)) return b;
	else return a;
}

int n;
int a[maxn];
int ans[maxn];
int w[maxn];
node t1,t2;
int main () {
	freopen("seq.in","r",stdin);
	freopen("seq.out","w",stdout);
	n = read();
	up[0].r = 2;
	low[0].r = 5;
	for(int i = 1;i <= n; ++i) {
		a[i] = read();
		t1 = up[i - 1];
		if(t1.r + 1 > 2) {
			t1.l ++;
			t1.r = 1;
		}
		else t1.r ++;
		t2.l = a[i];
		t2.r = 2;
		if(a[i]) {
			up[i] = Min(t1,t2);
		}
		else up[i] = t1;
		t1 = low[i - 1];
		if(t1.r + 1 > 5) {
			t1.l ++;
			t1.r = 1;
		}
		else {
			t1.r ++;
		}
		t2.r = 1;
		if(a[i]) {
			low[i] = Max(t1,t2);
		}
		else low[i] = t1;
	}
	if(a[1] > 1) {
		puts("-1");
		return 0;
	}
	if(up[n].r == 1) {
		up[n].l --;
	}
	for(int i = 1;i <= n; ++i) {
		if(a[i]) {
			if(a[i] < low[i].l || a[i] > up[i].l) {
				puts("-1");
				return 0;
			}
			ans[i] = a[i];
		}
		if(up[i].l < low[i].l) {
			puts("-1");
			return 0;
		}
	}
	ans[n] = up[n].l;
	w[ans[n]] ++;
	for(int i = n - 1;i; --i) {
		if(!a[i]) {
			ans[i] = min(ans[i + 1],up[i].l);
			if(w[ans[i]] == 5) {
				ans[i] --;
			}
		}
		w[ans[i]] ++;
	}
	printf("%d\n",ans[n]);
	for(int i = 1;i <= n; ++i) {
		printf("%d ",ans[i]);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/akoasm/p/9579429.html