[玄学]JZOJ 5811 简单的填数
分析
这道题我们可以维护二元组(x表示值,y表示之前这个值出现的最长长度)
两个二元组,up和down,up表示x尽可能大,down相反
那么显然遇到已经有数填在那个位上的情况是要处理一下的,我们只需要取一波最值
an要尽可能大的话就从upn取值,判断一下upn.y是否只为1,要特殊搞一下
最后反过来做一遍就得到序列了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <memory.h> using namespace std; const int N=2e5+1; int n; int a[N],cnt[N]; struct Eyz { int x,y; bool operator < (const Eyz &a) const {return x<a.x||x==a.x&&y<a.y;} }up[N],dn[N]; 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) {printf("-1");return 0;} up[1].x=up[1].y=dn[1].x=dn[1].y=1; for (int i=2;i<=n;i++) { if (up[i-1].y+1>2) { up[i].x=up[i-1].x+1;up[i].y=1; } else up[i].x=up[i-1].x,up[i].y=up[i-1].y+1; if (dn[i-1].y+1>5) { dn[i].x=dn[i-1].x+1;dn[i].y=1; } else dn[i].x=dn[i-1].x,dn[i].y=dn[i-1].y+1; if (a[i]) { Eyz u,d; u.x=a[i];u.y=2; d.x=a[i];d.y=1; up[i]=min(up[i],u); dn[i]=max(dn[i],d); if (up[i].x<a[i]||dn[i].x>a[i]) {printf("-1");return 0;} } } Eyz ans=up[n]; if (ans.y==1) {ans.x--;ans.y=5;} if (ans<dn[n]) {printf("-1");return 0;} a[n]=ans.x;cnt[ans.x]++; for (int i=n-1;i>=1;i--) { a[i]=min(a[i+1],up[i].x); if (cnt[a[i]]==5) a[i]--; cnt[a[i]]++; } printf("%d\n",ans.x); for (int i=1;i<=n;i++) printf("%d ",a[i]); fclose(stdin);fclose(stdout); }
在日渐沉没的世界里,我发现了你。