Rikka with A Long Colour Palette 贪心

H. Rikka with A Long Colour Palette

time limit per test

6.0 s

memory limit per test

1024 MB

input

standard input

output

standard output

Blue, the colour of the sky, the sea and your eyes.

Green, the colour of nature, fertility and life.

Purple, the colour of good judgment, and of people seeking spiritual fulfilment.

Orange, the only colour that is also a fruit.

Yellow, the colour in smiley faces.

Red, the warmest of all.

Rikka loves them all, but what is her favourite colour? She has found kk different colours, numbered from 11 to kk, and she knows that the best colour should be the one after mixing them all together. The best colour is called the DREAM.

Rikka has also prepared a long and narrow colour palette of length 109109. She designates nn segments in the palette. A segment described by two integers ll and rr (0≤l<r≤1090≤l<r≤109) represents an area of the palette where the distance between the leftmost end of the palette and the left endpoint (resp. the right endpoint) of the area is ll (resp. rr).

She will for each segment designated smear the pigment of any of these colours (from 11 to kk) which she has found evenly on it. Some areas may contain pigments of several different colours, since these segments may intersect. If some areas contain all these kk different colours which she has found, it would blend into the DREAM.

Now, Rikka wants you to maximize the total length of all areas in the palette such that each part of them can blend into the DREAM. You also need to provide a feasible plan.

Input

The input contains several test cases, and the first line contains a single integer TT (1≤T≤10001≤T≤1000), the number of test cases.

For each test case, the first line contains two integers nn (1≤n≤2×1051≤n≤2×105), the number of segments designated by Rikka, and kk (1≤k≤2×1051≤k≤2×105), the number of colours which Rikka has found.

Each of the following nn lines contains two integers ll and rr (0≤l<r≤1090≤l<r≤109), representing the ii-th segment in the palette.

The input guarantees that the sum of nn in all test cases is at most 2×1062×106.

Output

For each test case, output two lines. Firstly, output a line with a single integer, the largest total length of areas required. Then, output a line with nn space-separated integers describing a feasible plan, where the ii-th number is the colour for the ii-th segment.

All feasible plans are allowed, so you can output any of them.

Example

input

Copy

1
3 2
1 5
2 4
3 6

output

Copy

3
1 2 2

 

题目大意:给出n个线段,k种颜色,问如果给每个线段一种颜色,总共有多长的区间被k种颜色覆盖。

并且输出一种颜色分配方案。

解题思路:每一段的贡献分开考虑,首先将2*n个点排序,注意的一点是(如果两个点相同则右端点在前边)。

我们把未使用过的颜色放到一个数组里。

如果当前颜色都分配完了。说明该点和上一个点之间这个区间被颜色覆盖了k次。

如果当前点是左端点,并且有未分配的颜色,则直接分配一个颜色。

如果颜色都分配完了,我们不能随意给他一个颜色,因为他还能影响到后边的区间,所以先把当前的区间存起来。等到

有可用的颜色后再分配颜色。

如果当前点是右端点,我们需要知道这一段分配颜色了吗?

如果没有分配颜色说明这一段区间没有贡献(被另一个线段完全包含),我们随便给他一个颜色。

如果分配了颜色,我们就可以把这个颜色收回了。用于下一段的颜色分配(分配给待确定的或者下一段区间)。

需要注意的是:我们将待分配的区间存起来的时候是遇到了这个区间的左端点,但是没有颜色能够分配了。

但是遇到右端点的时候我们会给没有贡献的区间随便一个颜色。所以说,待分配的(并不是真正的待分配可能被随便分配了一个颜色)要判断一下是不是被随便分配过了。

思路来自:陈鑫

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define sca(x) scanf("%d",&x)
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define fir first
#define sec second

const int N  = 2e5+5;
typedef pair<int,int>pii;
vector<pii>V;

bool operator < (pii a,pii b)
{
    if(a.fir==b.fir)return (a.sec)<(b.sec);
    return a.fir < b.fir;
}

stack<int>col,rcol;
int mark[N];

void init()
{
    while(col.size())col.pop();
    while(rcol.size())rcol.pop();
    memset(mark,0,sizeof(mark));
    V.clear();
}

int main()
{
    int T;
    sca(T);
    while(T--)
    {
        int n,k;
        sca(n),sca(k);
        init();
        for(int i=1;i<=n;i++)
        {
            int l,r;
            sca(l),sca(r);
            V.pb(mp(l,i));
            V.pb(mp(r,-i));
        }
        sort(V.begin(),V.end());
        for(int i=1;i<=k;i++)col.push(i);
        LL ans=0;
        for(int i=0;i<V.size();i++)
        {
            if(col.size()==0)ans+=V[i].fir-V[i-1].fir;
            if(V[i].sec>0)
            {
                if(col.size()==0)rcol.push(V[i].sec);
                else {mark[V[i].sec]=col.top();col.pop();}
            }
            else
            {
                if(mark[-V[i].sec])
                {
                    col.push(mark[-V[i].sec]);
                }
                else mark[-V[i].sec]=1;
            }

            while(rcol.size()!=0&& col.size()!=0)
            {
                int tmp1=rcol.top();
                int tmp2=col.top();
                rcol.pop();
                if(mark[tmp1])continue;
                col.pop();
                mark[tmp1]=tmp2;
            }
        }
        cout<<ans<<endl;
        for(int i=1;i<=n;i++)
        {
            printf("%d",mark[i]);
            if(i==n)printf("\n");
            else printf(" ");
        }
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值