1. 程式人生 > >JZOJ5811. 【NOIP提高A組模擬2018.8.13】簡單的填數

JZOJ5811. 【NOIP提高A組模擬2018.8.13】簡單的填數

這裡寫圖片描述

Data Constraint

對於 30% 的資料,n ≤ 1000;
對於另外 30% 的資料,資料保證隨機生成;
對於 100% 的資料,2 ≤ n ≤ 2 × 10^5 , 0 ≤ ai ≤ 10^5。

題解

這個很顯然是特殊構造,
設一個二元組(x,l)擺在這個位置是x,而且這個是連續的第l個x。
設上界為up,下界為down。
因為要使得最終最大,所以up就是到l=2的時候就x++,
而相反down要儘可能小,所以只有當l=5時才x++。

如果遇到一個已經填了數的位置
就將up跟(ai,2)去min,因為填2之後就下一個位置就可以加1了,
那麼down就跟

(ai,1)去max,因為填1之後,還可以填更多的x。

判斷合法就很簡單,
1、上界跟下界之間沒有數可以填,
2、原來已經有數的位置並不在上下界之間。
3、第一個位置填的不是1

最後,就是將整個序列還原,從最後一個位置開始,
每個數跟它後面一個數,還有上界去min,如果這個數出現的次數超過5,
就x–。

code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h> #include <time.h> #define ll long long #define N 200003 #define M 103 #define db double #define P putchar #define G getchar #define inf 998244353 #define pi 3.1415926535897932384626433832795 using namespace std; char ch; void read(int &n) { n=0; ch=G(); while
((ch<'0' || ch>'9') && ch!='-')ch=G(); ll w=1; if(ch=='-')w=-1,ch=G(); while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G(); n*=w; } struct node { int x,l; }up[N],down[N],t,tt; node max(node a,node b) { if(a.x>b.x || (a.x==b.x && a.l>b.l))return a; return b; } node min(node a,node b) { if(a.x>b.x || (a.x==b.x && a.l>b.l))return b; return a; } void write(ll x){if(x>9) write(x/10);P(x%10+'0');} int n,a[N],ans[N],v[N]; int main() { freopen("seq.in","r",stdin); freopen("seq.out","w",stdout); read(n);up[0].l=2;down[0].l=5; for(int i=1;i<=n;i++) { read(a[i]); t=up[i-1]; if(t.l+1>2)t.x++,t.l=1;else t.l++; tt.x=a[i];tt.l=2; if(a[i])up[i]=min(t,tt);else up[i]=t; t=down[i-1]; if(t.l+1>5)t.x++,t.l=1;else t.l++; tt.l=1; if(a[i])down[i]=max(t,tt);else down[i]=t; } if(a[1]>1) { printf("-1"); return 0; } if(up[n].l==1)up[n].x--; for(int i=1;i<=n;i++) { if(a[i]) { if(a[i]<down[i].x || a[i]>up[i].x) { printf("-1"); return 0; } ans[i]=a[i]; } if(up[i].x<down[i].x) { printf("-1"); return 0; } } v[ans[n]=up[n].x]++; for(int i=n-1;i;i--) { if(!a[i]) { ans[i]=min(ans[i+1],up[i].x); if(v[ans[i]]==5)ans[i]--; } v[ans[i]]++; } printf("%d\n",ans[n]); for(int i=1;i<=n;i++) write(ans[i]),P('\n'); return 0; }