Dreamoon Likes Coloring(構造+思維題) Codeforces Round #631 (Div. 2)

在這裏插入圖片描述

題目大意

       給n(n<=100000)n(n<=100000)個待染色的格子,給mmlil_i,對應mm次染色過程(mm種顏色),第ii次染色的區間範圍爲[pi,pi+li1][p_i,p_i+l_i-1],其中,pip_i的值可從區間[1,nli+1][1,n-l_i+1]中任選。每一個格子最終的顏色爲最後一次對其染色的值,要求構造使得每一個格子都被染色且mm種顏色均出現的染色方案,如果不存在則輸出1-1

分析過程

       這一道題乍一看無從下手(乍二看也是 )。首先想到一種情形,如果所有染色區間的長度之和小於nn的話是肯定不存在有效方案的(即li<n\sum l_i<n,此時nn個格子無法被全部染色),此時直接輸出1-1
       接下來,我們嘗試每一次染色的左端點都比上一次染色向後偏移一位這種構造方式,即第ii次染色區間的pi=ip_i=i,這樣可以保證每一個染色區間中至少左端點不會被後面的染色區間覆蓋,但是我們可以發現,如果在第ii次染色的時候,pip_i能夠取到的最大值比ii還小,即nli+1<in-l_i+1<i的時候,是沒辦法繼續構造下去的,這個時候,我們注意到,如果出現這種情形必然不存在構造方案,因爲此時第ii次染色區間的長度已經大於ni+1n-i+1了,給前面的染色只留下了<i1<i-1個獨立空位,因此前面的i1i-1個染色區間中必然存在被完全覆蓋的區間。所以,這個時候也是直接輸出1-1即可。
       這時候我們繼續順着之前染色區間左端點不斷+1+1的方式進行構造,會發現,如果每次染色都這樣做,可能最後會存在一些格子沒有被染色,所以在後續的染色中必然要更加大膽的擴大染色區間纔可以。可以設suff[i]suff[i]lil_i的後綴和,我們考慮從後往前染色:當剩餘的染色格子數目大於剩餘染色的次數ii時,pi=suff[i]p_i=suff[i];當等於ii時,這個時候剛好可以每一次將左端點向左擴展一位而實現剩餘全部格子的染色。即pi=max(i,nsuff[i]+1)p_i=max(i, n-suff[i]+1)

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;
} 

點個贊再走撒~~~!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章