1. 程式人生 > >2018 ICPC 徐州區域賽 H Rikka with A Long Colour Palette

2018 ICPC 徐州區域賽 H Rikka with A Long Colour Palette

 

題意:
給出n個數軸上的線段,進行每個線段染一種顏色,求混合有k種顏色的距離的和。

題解:

如果某一段被k條及以上線段覆蓋,那麼這一段一定是滿足條件的,問題是如何求解方案數。

確定一條線段染什麼顏色一定是根據左右端點判斷得到的,所以我們只關心端點。

將左端點記為1,右端點記為-1,排序,相同的位置,右端點更靠前。

用一個佇列儲存沒有染色的點,一開始所有顏色都在佇列。

從小到大列舉位置

如果是左端點,並且佇列不為空,我們就將這個線段染成隊首的顏色

如果是右端點,如果這條線段染過色,就將該顏色放入隊尾,進行回收

但是有幾個細節要考慮

左端點時,如果所有顏色都染了,該染什麼顏色?隨便染嗎?不是的,因為可能後面可能會用到,解決方法是將其將放入佇列(棧)中,留著以後再用

什麼時候用?

假如說處理完這個位置後,發現覆蓋的顏色不夠k種,這時我們就看之前存下來的線段,如果還沒有被染色,就取出來染色。

這樣就能利用起來所有的線段了

程式碼:

#include<bits/stdc++.h>
#define N 200010
#define INF 0x3f3f3f3f
#define eps 1e-10
#define pi 3.141592653589793
#define P 998244353
#define LL long long
#define pb push_back
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;

struct dd
{
    int x,y,id;
    bool operator < (const dd d)const
    {
        return x==d.x?y<d.y:x<d.x;
    }
}a[N<<1];

int col[N];

int main()
{
    int T;
    sc(T);
    while(T--)
    {
        int n,m;
        scc(n,m); int cn=0; mem(col);
        for (int i=1;i<=n;i++)
        {
            int x,y;
            scc(x,y);
            a[++cn]=dd{x,1,i};
            a[++cn]=dd{y,-1,i};
        }
        sort(a+1,a+cn+1);
        queue<int> q; stack<int> st;
        for (int i=1;i<=m;i++) q.push(i);
        int t=0,k=1,prek=0,pret=0,ans=0;
        while(k<=cn)
        {
            int p=k;
            while(a[p].x==a[k].x)
            {
                if (a[p].y==-1)
                {
                    int r=a[p].id;
                    if (col[r]!=0)
                    {
                        t--;
                        q.push(col[r]);
                    }else col[r]=1;
                }
                if (a[p].y==1)
                {
                    int r=a[p].id;
                    if (t>=m) {st.push(r);} else
                    {
                        t++;
                        col[r]=q.front();
                        q.pop();
                    }
                }
                p++;
            }
            while(t<m)
            {
                while(!st.empty() && col[st.top()]) st.pop();
                if (st.empty()) break;
                t++;
                int r=st.top(); st.pop();
                col[r]=q.front();
                q.pop();
            }
            if (pret>=m) ans+=(a[k].x-prek);
            pret=t;
            prek=a[k].x;
            k=p;
        }
        printf("%d\n%d",ans,col[1]);
        for (int i=2;i<=n;i++) printf(" %d",col[i]); puts("");
    }
}