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("");
    }
}

 

猜你喜欢

转载自blog.csdn.net/nudt_spy/article/details/84778483