题解
非常容易想到的线段树, 还可以用并查集来。 还有一位大神用了$O(n)$ 就过了Orz
要判断是否能染色出输入给出的序列,必须满足两个条件:
1、 序列中必须存在一个$q$
2、 两个相同的数$x$的中间不存在比 $ x$ 小的数
首先判断输入的数列中是否存在$q$, 若不存在$q$ 且没有 $a_i = 0$, 表示序列中一定没有$q$, 直接输出NO
若存在某个$a_i = 0$ , 将任意一个染成$q$即可
然后我们再查询两个相同的数$x$ 中是否存在比$x$ 小的数,用线段树来维护区间最小即可实现
接着把两个$x$中间的序列染色, 用MinOK来记录,表示区间内$a_i = 0$,可以染色的最小值。 (线段树区间修改
最后把$a_i = 0$ 进行染色(利用线段树点查询
CF现场就想到的算法,然而没有特判存在$q$,pushdown还少打了唔, CF百分百掉分,我要变成pupil了,太惨啦QAQ
代码
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 #define lson nd<<1 5 #define rson nd<<1|1 6 #define rd read() 7 #define rep(i,a,b) for(int i = (a); i <= (b); ++i) 8 #define per(i,a,b) for(int i = (a); i >= (b); --i) 9 using namespace std; 10 11 const int N = 3e5, inf = ~0U >> 2; 12 13 int MIN[N << 2], a[N], L[N], R[N], lazy[N << 2], q, n, pos; 14 int Mok[N << 2]; 15 16 int read() { 17 int X = 0, p = 1; char c = getchar(); 18 for(; c > '9' || c < '0'; c = getchar()) if( c == '-') p = -1; 19 for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0'; 20 return X * p; 21 } 22 23 void update(int nd) { 24 MIN[nd] = min(MIN[lson], MIN[rson]); 25 } 26 27 void pushdown(int nd) { 28 if(lazy[nd]) { 29 Mok[lson] = lazy[nd]; 30 Mok[rson] = lazy[nd]; 31 lazy[lson] = lazy[rson] = lazy[nd]; 32 lazy[nd] = 0; 33 } 34 } 35 36 void build(int l, int r, int nd) { 37 if(l == r) { 38 MIN[nd] = a[l] == 0 ? inf : a[l]; 39 return; 40 } 41 int mid = (l + r) >> 1; 42 build(l, mid, lson); 43 build(mid + 1, r, rson); 44 update(nd); 45 } 46 47 int query(int Li, int Ri, int l, int r, int nd) {//查询区间最小 48 if(Li <= l && r <= Ri) return MIN[nd]; 49 int mid = (l + r) >> 1, re = inf; 50 if(Li <= mid) re = min(re, query(Li, Ri, l, mid, lson)); 51 if(mid < Ri) re = min(re, query(Li, Ri, mid + 1, r, rson)); 52 return re; 53 } 54 55 int query_pt(int p, int l, int r, int nd) {//查询可以染上的值 56 if(l == r) return Mok[nd]; 57 int mid = (l + r) >> 1; 58 pushdown(nd); 59 if(p <= mid) return query_pt(p, l, mid, lson); 60 else return query_pt(p, mid + 1, r, rson); 61 } 62 63 void change(int Li, int Ri, int c, int l, int r, int nd) { 64 if(Li <= l && r <= Ri) { 65 lazy[nd] = c; 66 Mok[nd] = c; 67 return; 68 } 69 int mid = (l + r) >> 1; 70 pushdown(nd); 71 if(Li <= mid) change(Li, Ri, c, l, mid, lson); 72 if(mid < Ri) change(Li, Ri, c, mid + 1, r, rson); 73 update(nd); 74 } 75 76 int main() 77 { 78 n = rd; q = rd; 79 for(int i = 1; i <= n; ++i) { 80 a[i] = rd; 81 if(!a[i]) pos = i; 82 if(!L[a[i]]) L[a[i]] = i; 83 R[a[i]] = i; 84 } 85 if(!L[q] && !pos) return printf("NO "), 0;//无a[i]=0也无q 86 build(1, n, 1); 87 for(int i = 1; i <= q; ++i) {//必须按颜色从小到大覆盖 88 if(!L[i]) continue; 89 int minv = query(L[i], R[i], 1, n, 1); 90 if(minv < i) return printf("NO "), 0; 91 change(L[i], R[i], i, 1, n, 1); 92 } 93 for(int i = 1; i <= n; ++i) if(!a[i]) { 94 a[i] = query_pt(i, 1, n, 1); 95 if(i == pos && !L[q]) a[i] = q; // 必须存在q 96 else if(!a[i]) a[i] = 1; 97 } 98 printf("YES "); 99 for(int i = 1; i <= n; ++i) printf("%d ", a[i]); 100 putchar(' '); 101 }