【Codeforces 1329A】Dreamoon Likes Coloring
阿新 • • 發佈:2020-12-09
題目連結
翻譯
讓你按順序對連續的點進行染色(總共有 \(m\) 個連續塊需要染色)
你可以指定這個連續塊的區間,但是長度必須是 \(li\) (但不能超過邊界)
然後後面的染色會覆蓋前面的染色,且每個連續塊的染色(要染的顏色)都不一樣。
要求 \(m\) 次染色過後,所有 \(m\) 種顏色都至少還存在一個位置。且每個點(1-n)都至少被染色過一次。
題解
兩種情況:
第 \(1\) 種,所有的 \(l\) 的值加起來還不到 \(n\),那麼無論怎麼染色都有點沒染到。無解
第 \(2\) 種,考慮最緊湊的染色方法,即第 \(i\) 次染色的位置 \(p[i] = p[i-1] + 1\)
對於這種緊湊的染色方法,如果某個位置還有 \(i+l[i]-1>n\) 這就說明第 \(i\) 種顏色無論怎麼染,都會讓前面的某些顏色消失。所以無解。
我們考慮這兩種情況,其實就對應了寬鬆和緊湊兩種染色方法,寬鬆也即所有的染色連續塊都不相交。緊湊也即連續兩個染色塊非常緊湊地連在一起。
那我們直接用第二種方法不就行了?
但是有一個問題,就是隻用第二種方法的話,可能會出現在後面某些位置沒有染上色的情況,所以得寬鬆和緊湊兩種方法結合使用。
開始的時候後面所有的 \(l[i]\)
一旦某個時刻後面所有的 \(l[i]\) 的值加上當前位置比 \(n\) 小了,或者等於了。這說明,再這樣緊湊著擺的話,就不夠 \(n\) 個格子都染上色了。
則我們從最後一段 \([n-l[n]+1,n]\) 開始寬鬆的擺(倒數第二段是\([n-l[n]-l[n-1]+1,n-l[n]]\),直到和上一個 \(p[i-1]=i-1\) 的緊湊擺法覆蓋的區域有交集為止。
程式碼1
#include <bits/stdc++.h> #define LL long long using namespace std; const int N = 1e5; int n, m; int l[N + 10]; int main(){ scanf("%d%d",&n,&m); LL rest = 0; for (int i = 1;i <= m; i++){ scanf("%d",&l[i]); rest += l[i]; } if (rest < n){ puts("-1"); return 0; } for (int i = 1;i <= m; i++){ if (i + l[i] - 1 > n){ puts("-1"); return 0; } } for (int i = 1;i <= m; i++){ if (i + rest - 1 > n){ printf("%d",i); }else{ printf("%d",n - rest + 1); } if (i == m){ puts(""); }else{ putchar(' '); } rest -= l[i]; } return 0; }