Codeforces 497C Distributing Parts set+贪心

本文探讨了在有限资源条件下,如何高效地分配任务给不同能力的个体,以实现任务的最大化完成。通过将人与任务按优先级排序,利用集合操作进行资源匹配,最终输出最优任务分配方案。

题目链接:点击打开链接

题意:

给定n个任务

下面[l, r]是n个任务需要占用的时间。

m个人

下面是m个人的空闲时间以及这个人至多能做的任务个数(一个人同一时刻只能做一个任务,即人是单线程的)

[l, r] num

问:

若任务不能被全部完成则输出NO

否则输出YES

输出每个任务是谁完成的。

思路:

把人和任务放一起按右端点排序。

若遇到了任务则把任务的左端点放到set里。

若遇到了人,则把set中>=人的左端点的 num个数删掉。

java:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
public class Main {
	static int N = 200050;
	class Edge implements Comparable<Edge>{
		long id, l;
		public int compareTo(Edge o){
			if(l != o.l)return Long.compare(l, o.l);
			return Long.compare(id, o.id);
		}
	}
	Edge edge(long a, long b){
		Edge tmp = new Edge();
		tmp.id = a; tmp.l = b;
		return tmp;
	}
	class Node implements Comparable<Node>{
		long l, r, id, num, op;
	/*	public Node(long a, long b, long c, long d, long e){
			l = a; r = b; c = id; d = num; e = op;
		}/**/
		public int compareTo(Node o){
			if(r != o.r)
				return Long.compare(r, o.r);
			return Long.compare(op, o.op);
		}
	}
	Node cr(long a, long b, long c, long d, long e){
		Node tmp = new Node();
		tmp.l = a; tmp.r = b; tmp.id = c; tmp.num = d; tmp.op = e;
		return tmp;
	}
	int[] b = new int[N], ans = new int[N];
	ArrayList<Node> a = new ArrayList<>();
	int n, m;
	void init(){
		n = cin.nextInt();
		long l, r, num;
		for(int i = 1; i <= n; i++)
		{
			l = cin.nextLong(); r = cin.nextLong();
			a.add(cr(l, r, (long)i, 0L, 0L));
		}
		m = cin.nextInt();
		for(int i = 1; i <= m; i++)
		{
			l = cin.nextLong(); r = cin.nextLong(); num = cin.nextLong();
			a.add(cr(l, r, (long)i, num, 1L));			
		}
		Collections.sort(a);
	}
	TreeSet set = new TreeSet();
	Iterator p;
	public void work(){
		init();
		set.clear();
		set.add(edge(-1,0));
		int siz = 0;
		for(int i = 0; i < a.size(); i++)
		{
			if(a.get(i).op == 1){
				while(set.size()>0 && a.get(i).num-->0){
					Edge E = (Edge) set.ceiling(edge(0L, a.get(i).l));
					if(E==null)break;
					siz++;
					ans[(int)E.id] = (int)a.get(i).id; 
					set.remove(E);
				}
			}
			else 
				set.add(edge(a.get(i).id, a.get(i).l));
		}
		if(siz == n){
			System.out.println("YES");
			for(int i = 1; i <= n; i++)
				System.out.print(ans[i]+" ");
		}
		else System.out.println("NO");
	}
	Main() {  
        cin = new Scanner(System.in);  
    }  
    public static void main(String[] args) {
        Main e = new Main();  
        e.work();
    }
    public Scanner cin;
}


c:

#include <bits/stdc++.h>
template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if(c=getchar(),c==EOF) return 0;
    while(c!='-'&&(c<'0'||c>'9')) c=getchar();
    sgn=(c=='-')?-1:1;
    ret=(c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    ret*=sgn;
    return 1;
}
template <class T>
inline void pt(T x) {
    if (x <0) {
        putchar('-');
        x = -x;
    }
    if(x>9) pt(x/10);
    putchar(x%10+'0');
}
using namespace std;
typedef long long ll;
#define int ll
const int N = 200050;
int n, m;
struct node{
    int op, l, r, num, id;
}a[N*2];
bool cmp(node x, node y){
    if(x.r != y.r)
        return x.r<y.r;
    if(x.op!=y.op)
        return x.op<y.op;
}
int top, b[N];
void input(){
    top = 0;
    for(int i = 1; i <= n; i++){
        rd(a[top].l); rd(a[top].r);
        a[top].op = 0;
        a[top].id = i;
        top++;
    }
    rd(m);
    for(int i = 1; i <= m; i++){
        rd(a[top].l); rd(a[top].r); rd(a[top].num);
        a[top].op = 1;
        a[top].id = i;
        top++;
    }
    sort(a, a+top, cmp);
}
struct Edge{
    int id, l;
    bool operator<(const Edge&e)const{
        if(e.l!=l)return e.l>l;
        return e.id>id;
    }
    Edge(int a=0,int b=0):id(a),l(b){}
}tmp;
set<Edge>s;
set<Edge>::iterator p;
#undef int
int main(){
#define int ll
    while(cin>>n){
        input();
        int ans = 0;
        s.clear();
        for(int i = 0; i < top; i++){
            if(a[i].op){
                while(s.size() && a[i].num--)
                {
                    p = s.lower_bound(Edge(0, a[i].l));
                    if(p == s.end())break;
                    tmp = *p;
                    b[tmp.id] = a[i].id;
                    s.erase(p);
                    ans++;
                }
            }
            else {
                s.insert(Edge(a[i].id, a[i].l));
            }
        }
        if(ans == n)
        {
            puts("YES");
            for(int i = 1; i <= n; i++){pt(b[i]); putchar(' ');}
        }
        else puts("NO");
    }
    return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值