2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest- H. Rikka with A Long Colour Palette -思維+貪心

【Problem Description】
有\(k\)種顏色,給你\(n\)個區間段,選擇一種合適的方案給每個區間段染色,使得最終染色次數等于\(k\)次的長度和最大,
【Solution】
將左右端點放在一起排序,但是標記出它是左端點,還是右端點,并且記錄每個端點屬于第幾個區間,排序后,對于每個左端點,從未使用過的顏色中選一個染色此區間,若連續染色超過\(k\)次,則多于的區間放入堆疊中備用,當某次染色小于\(k\)次時拿出來染色,當遇到右端點時,若這段區間染過色,則將此顏色識訓,若沒染過色,隨意染色即可,
最重要的,一定要按格式輸出,末尾不能有空格
【Code】
/*
* @Author: _Simon_
* @Date: 2019-10-30 10:44:14
* @Last Modified by: Simon
* @Last Modified time: 2019-10-30 10:44:14
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 200005
#define INF 0x3f3f3f3f
struct node{
int first,second,ord;
node(){}
node(int first,int second,int ord):first(first),second(second),ord(ord){}
bool operator <(const node&a) const{
if(first==a.first) return second<a.second;
return first<a.first;
}
};
vector<node>a;
int ans[maxn];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int T;cin>>T;
while(T--){
memset(ans,0,sizeof(ans));
a.clear();
int n,k;cin>>n>>k;
for(int i=1;i<=n;i++){
int l,r;cin>>l>>r;
a.push_back({l,1,i});
a.push_back({r,-1,i});
}
sort(a.begin(),a.end());
queue<int>q;stack<int>st;
for(int i=1;i<=k;i++) q.push(i);
int tmp=0,pret=0,preidx=0;
for(int i=0;i<a.size();i++){
if(a[i].second>0){ //左端點
if(tmp<k){ //連續染色小于k次
tmp++;
ans[a[i].ord]=q.front();q.pop(); //從未染色的顏色中選出一個染色
}else{
st.push(a[i].ord); //染色大于k次,備用
}
}else{ //右端點
if(ans[a[i].ord]){ //若所在區間染過色
q.push(ans[a[i].ord]); //識訓顏色
tmp--;
}else{
ans[a[i].ord]=1; //否則隨意染色
}
}
if(i+1<a.size()&&a[i].first==a[i+1].first) continue; //同樣端點一起處理
while(tmp<k){ //若染色小于k次,從備用端點中選取
while(!st.empty()&&ans[st.top()]) st.pop();
if(st.empty()) break;
tmp++;
ans[st.top()]=q.front();st.pop();q.pop();
}
if(pret>=k) ans[0]+=a[i].first-preidx; //計算染色次數等于k次的長度
preidx=a[i].first;pret=tmp;
}
cout<<ans[0]<<endl;
for(int i=1;i<=n;i++) cout<<ans[i]<<" \n"[i==n]; //按格式輸出
}
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/136670.html
標籤:其他
上一篇:希爾排序
