题目链接:https://codeforces.com/gym/102012
题意不再赘述。
这里看到海大过了,感觉是个不难的题,也想到了贪心,但是后面求方案卡住了。感觉是自己状态有问题吧,后面其实应该想出来的,题解有的都想到过,但是就是整合不到一起。
首先,可以肯定,如果一段区间被覆盖超过K次一定会满足题意。证明不会,但是跑了几组复杂一点的数据都没卡住。
然后想怎么找方案数。很显然需要离散化一下,离散化之后,我们考虑贪心的填颜色。每次只要这个区间还没被所有颜色覆盖,就填一种不同的颜色,具体实现方法是用一个q_col队列,队列里存的都是当前没填的颜色。剩下的就都是细节了。
细节:
1:如果遇到一个左端点,但是当前区间已经被全覆盖了,那么我不能乱填,因为这个填色有后效性,我先存下来,等到后面再用。实现方法是用一个q_seg队列。
2:当且仅当当前节点时q_col队列为空才可能更新到答案,因为此时,上一个点一定是恰好K中颜色,当前点也是。
3:如果一个线段在左端点时它多余,再右端点时海没有颜色,说明这个线段是完全多余的,随便赋一个小于等于k的颜色即可。
4:q_seg的用途,是在每次遇到端点的时候判断是否要用的。同时每次判断不会出错。
证明:
①:如果这个线段无用,一定会在碰到它右端点的时候给它赋值,这里我们会特判这个线段是否有颜色。
②:如果它有用,它一定会在遇到右端点之前备用上,也就是赋值上一种颜色。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<ctime>
#define up(i,x,y) for(int i = x;i <= y;i ++)
#define down(i,x,y) for(int i = x;i >= y;i --)
#define mem(a,b) memset((a),(b),sizeof(a))
#define mod(x) ((x)%MOD)
#define lson p<<1
#define rson p<<1|1
using namespace std;
typedef long long ll;
const int SIZE = 400010;
const int INF = 2147483640;
const double eps = 1e-8;
inline void RD(int &x)
{
x = 0; char c; c = getchar();
bool flag = 0;
if(c == '-') flag = 1;
while(c < '0' || c > '9') {if(c == '-') {flag = 1;} c = getchar();}
while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0',c = getchar();
}
struct Line{
int pos,id;
// Line(int a,int b):pos(a),id(b){}
}seg[SIZE];
int t,n,k,l,r,ans;
int col[SIZE];
queue <int> q_col,q_seg;
bool cmp(Line &a,Line &b){return a.pos == b.pos ? a.id < b.id : a.pos < b.pos;}
int main(int argc, char const *argv[])
{
scanf("%d",&t);
while(t--)
{
ans = 0;
scanf("%d%d",&n,&k);
while(!q_col.empty()) q_col.pop();
while(!q_seg.empty()) q_seg.pop();
for(int i = 1;i <= n;i ++)
{
scanf("%d%d",&l,&r);
seg[i].pos = l;
seg[n+i].pos = r;
seg[i].id = i;
seg[n+i].id = -i;
col[i] = 0;
}
for(int i = 1;i <= k;i ++) q_col.push(i);
sort(seg+1,seg+1+2*n,cmp);
for(int i = 1;i <= 2*n;i ++)
{
// printf("ans:%d\n",ans);
if(q_col.empty())
{
// printf("seg:%d %d\n",seg[i].pos,seg[i-1].pos);
ans += seg[i].pos - seg[i-1].pos;
}
if(seg[i].id > 0)//左端点
{
if(!q_col.empty())//填色
{
int now_color = q_col.front();
q_col.pop();
col[seg[i].id] = now_color;
}
else
{
q_seg.push(seg[i].id);
}
}
else//右端点
{
if(col[- seg[i].id]) q_col.push(col[- seg[i].id]);
else col[- seg[i].id] = 1;
}
while(!q_seg.empty() && !q_col.empty())
{
int tmp_seg_id = q_seg.front();
int tmp_col = q_col.front();
q_seg.pop();
if(col[tmp_seg_id]) continue;
col[tmp_seg_id] = tmp_col;
q_col.pop();
}
}
printf("%d\n",ans);
for(int i = 1;i <= n;i ++)
{
printf("%d%c",col[i],i == n ? '\n' : ' ');
}
}
return 0;
}