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

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


【Problem Description】

\(k\)種顏色,給你\(n\)個區間段,選擇一種合適的方案給每一個區間段染色,使得最終染色次數等於\(k\)次的長度和最大。node

【Solution】

將左右端點放在一塊兒排序,可是標記出它是左端點,仍是右端點,而且記錄每一個端點屬於第幾個區間,排序後,對於每一個左端點,從未使用過的顏色中選一個染色此區間,若連續染色超過\(k\)次,則多於的區間放入棧中備用,當某次染色小於\(k\)次時拿出來染色。當遇到右端點時,若這段區間染過色,則將此顏色收回,若沒染過色,隨意染色便可。ios

最重要的,必定要按格式輸出,末尾不能有空格c++


【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;
}
相關文章
相關標籤/搜索