題目大意
給個待染色的格子,給個,對應次染色過程(種顏色),第次染色的區間範圍爲,其中,的值可從區間中任選。每一個格子最終的顏色爲最後一次對其染色的值,要求構造使得每一個格子都被染色且種顏色均出現的染色方案,如果不存在則輸出。
分析過程
這一道題乍一看無從下手(乍二看也是 )。首先想到一種情形,如果所有染色區間的長度之和小於的話是肯定不存在有效方案的(即,此時個格子無法被全部染色),此時直接輸出。
接下來,我們嘗試每一次染色的左端點都比上一次染色向後偏移一位這種構造方式,即第次染色區間的,這樣可以保證每一個染色區間中至少左端點不會被後面的染色區間覆蓋,但是我們可以發現,如果在第次染色的時候,能夠取到的最大值比還小,即的時候,是沒辦法繼續構造下去的,這個時候,我們注意到,如果出現這種情形必然不存在構造方案,因爲此時第次染色區間的長度已經大於了,給前面的染色只留下了個獨立空位,因此前面的個染色區間中必然存在被完全覆蓋的區間。所以,這個時候也是直接輸出即可。
這時候我們繼續順着之前染色區間左端點不斷的方式進行構造,會發現,如果每次染色都這樣做,可能最後會存在一些格子沒有被染色,所以在後續的染色中必然要更加大膽的擴大染色區間纔可以。可以設爲的後綴和,我們考慮從後往前染色:當剩餘的染色格子數目大於剩餘染色的次數時,;當等於時,這個時候剛好可以每一次將左端點向左擴展一位而實現剩餘全部格子的染色。即。
AC代碼
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 100;
typedef long long ll;
ll l[maxn], suff[maxn], p[maxn], n, m;
int main(){
int i, j;
ios::sync_with_stdio(false);
cin>>n>>m;
for(i=1;i<=m;++i){
cin>>l[i];
if(l[i] > n - i + 1){ //無法保證在i之前染色的每一個區間擁有至少一個獨立位置
cout<<-1;
return 0;
}
}
for(i=m;i>=1;--i){
suff[i] = suff[i+1] + l[i];
}
if(suff[1] < n) cout<<-1; //無法滿足全部上色
else{
for(ll i=1;i<=m;++i){ //更新答案
p[i] = max(i, n - suff[i] + 1);
}
for(i=1;i<m;++i) cout<<p[i]<<' ';
cout<<p[i]<<'\n';
}
return 0;
}
點個贊再走撒~~~!