• 联赛模拟17_简单的填数(贪心)



    贪心

    up[i]记录保证序列值最大的情况下的信息

    up.val:取值

    up.len: a[i]是第几个

    down相反

    我们将每个数的两种边界可能情况 1->n 更新出来,a[n]取上边界,倒着恢复序列即可

    对于每次有值的点,在保证符合的前提下尽量满足down和up的趋势,同时检验即可。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    const int maxn=2e5+5;
    const int maxa=1e5+5;
    int n;
    int a[maxn];
    int cnt[maxa];
    struct Node{
    	int val;
    	int len;
    }up[maxn],down[maxn];
    int main(){
    	freopen("seq.in","r",stdin);
    	freopen("seq.out","w",stdout);
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    	if(a[1]>1) goto END;
    	up[1].val=down[1].val=up[1].len=down[1].len=1;
    	for(int i=2;i<=n;++i){
    		up[i]=up[i-1],down[i]=down[i-1];
    		if(++up[i].len>2) up[i].val++,up[i].len=1;
    		if(++down[i].len>5) down[i].val++,down[i].len=1;
    		if(!a[i]) continue;
    		if(up[i].val>a[i]) up[i].val=a[i],up[i].len=2;
    		if(down[i].val<a[i]) down[i].val=a[i],down[i].len=1;
    		if(a[i]<down[i].val||a[i]>up[i].val) goto END;
    	}
    	if(up[n].len==1){
    		up[n].val--;
    		up[n].len=5;
    	}
    	if(up[n].val<down[n].val) goto END;
    	a[n]=up[n].val;
    	printf("%d
    ",a[n]);
    	cnt[a[n]]++;
    	for(int i=n-1;i>=1;--i){
    		if(!a[i]){
    			a[i]=min(up[i].val,a[i+1]);
    			if(cnt[a[i]]>=5) a[i]--;
    		}
    		cnt[a[i]]++;
    	}
    	for(int i=1;i<=n;++i) printf("%d ",a[i]);
    	return 0;
    	END: puts("-1"); return 0;
    }
    
  • 相关阅读:
    AppleID的双重认证
    swift 分组tableview 设置分区投或者尾部,隐藏默认间隔高度
    swift 警告框
    数组
    循环结构(二)
    循环结构
    选择结构
    选择结构
    变量 数据类型和运算符
    (五)Spring 中的 aop
  • 原文地址:https://www.cnblogs.com/Lour688/p/13821441.html
Copyright © 2020-2023  润新知