2018icpc 徐州h题

题目大意:

https://codeforces.com/gym/102012/problem/H?csrf_token=c9d0191a64a241166d54a565b1615125

区间[l , r] 中有n条线 问用k种颜色最多能染多少区间  并输出区间和r - l;

∑n <= 2e6,1 <= k <= 2e5,0 <= l < r <= 1e9。

解题思路:

把N*2 个端点排序, 对端点和颜色进行入队出队操作 当颜色为空时说明这个区间满足要求,并将此线段保留到延迟染色的队伍中等待下次染色

ac代码:

#include<bits/stdc++.h>
#define sz(x) ((int)x.size())
//#define mp(x, y) make_pair(x, y)
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAXN = 400010;
int T, n, k, col[MAXN];
struct Node{
    int st, id;
    Node(){}
    Node(int _st, int _id){//方便结构体赋值
        st = _st;  id = _id;
    }
    bool operator < (const Node &nd) const{//否则多定义一个cmd排序
        if(st == nd.st) return id < nd.id;
        return st < nd.st;
    }
}seg[MAXN];
queue<int> rCol, rSeg;
int main(){
    scanf("%d", &T);
    while(T --){
        scanf("%d%d", &n, &k);
        while(sz(rCol)) rCol.pop();
        while(sz(rSeg)) rSeg.pop();
        for(int i = 1; i <= n; i ++){
            int l, r;
            scanf("%d%d", &l, &r);
            col[i] = 0;
            seg[i] = Node(l, i);
            seg[i + n] = Node(r, -i);
        }
        if(n < k){
            printf("0\n1");
            for(int i = 2; i <= n; i ++)
                printf(" 1");
            printf("\n");
            continue;
        }
        sort(seg + 1, seg + 2*n + 1);
        for(int i = 1; i <= k; i ++)
            rCol.push(i);
        ll ans = 0;
        for(int i = 1; i <= 2*n; i ++){
            if(sz(rCol) == 0)//没有颜色可染,此端点到前个端点必满足条件
                ans += seg[i].st - seg[i - 1].st;
            if(seg[i].id > 0){//左端点进来
                if(sz(rCol)){//有颜色染色 ,没颜色放入延迟染色
                    int tc = rCol.front();
                    col[seg[i].id] = tc;
                    rCol.pop();
                }
                else
                    rSeg.push(seg[i].id);
            }
            else{//右端点出去
                if(col[- seg[i].id])//已经染色则归还颜色
                    rCol.push(col[- seg[i].id]);
                else//没有说明不做贡献
                    col[- seg[i].id] = 1;
            }
            while(sz(rCol) && sz(rSeg)){
                int tc = rCol.front();
                int ts = rSeg.front();
                rSeg.pop();
                if(col[ts]) continue;//归还了颜色没有出队
                col[ts] = tc;
                rCol.pop();
            }
        }
        printf("%I64d\n", ans);
        for(int i = 1; i <= n; i ++)
            printf("%d%c", col[i], i == n ? '\n' : ' ');
    }
    return 0;
}

 

posted @ 2019-07-19 11:22  YZBPXX  阅读(384)  评论(0编辑  收藏  举报