1 条题解

  • 0
    @ 2025-8-24 22:58:12

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar MinimumSpanningTree
    **

    搬运于2025-08-24 22:58:12,当前版本为作者最后更新于2024-04-20 12:39:08,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题目链接

    挺不错的一道贪心题。首先观察数据范围,xx 最小可以是 11yy 最大可以是 100100,根据收益可以计算出 1×500=5001\times500=500100×2=200100\times2=200,由此可见,在 xx 最小,yy 最大时,xx 带来的收益却比 yy 大。于是我们可以得出结论:无论如何,xx 的价值永远比 yy 大。这就是我们贪心的突破口,由此结论我们可以优先考虑 xx

    于是我们将机器和任务都按 xx 为第一关键字,yy 为第二关键字从大到小排序。接下来依次枚举任务,找出所有 xx 能满足当前任务的机器,再从这些机器里寻找满足 yy 的,如果存在多个机器可以满足,则我们贪心的选取 yy 最小的那个。因为 yy 并不是有序的,后面可能会出现更大的 yy,当然要尽量把大的留给后面的了。

    对于查找满足 xx 的机器:这时我们会发现,如果枚举每次任务的时候用遍历的方式寻找机器,O(nm)O(nm) 明显是超时的。但因为机器和任务的 xx 都是有序的,若当前机器不能满足任务,则后面的机器也不能,若某个机器满足当前任务,则它必定也满足下一个任务。故我们可以维护一个指针,每一轮查找新的可以满足的机器。

    对于查找满足 yy 的机器:与上面相同,直接枚举显然是超时的。但观察到 y100y\le100,容易想到我们可以使用一个数组 cic_i 表示 y=iy=i 的机器数量,O(100m)O(100m) 可以通过。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=100100,M=110;
    int n,m,c[M],p,cnt;
    ll ans;
    struct node
    {
    	ll x,y;
    }a[N],b[N];
    bool cmp(node a1,node a2)
    {
    	if(a1.x!=a2.x) return a1.x>a2.x;
    	return a1.y>a2.y;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) scanf("%lld%lld",&a[i].x,&a[i].y);
    	for(int i=1;i<=m;i++) scanf("%lld%lld",&b[i].x,&b[i].y);
    	//从大到小排序 
    	sort(a+1,a+n+1,cmp);
    	sort(b+1,b+m+1,cmp);
    	for(int i=1;i<=m;i++)//枚举任务 
    	{
    		while(p<n&&a[p+1].x>=b[i].x)//维护指针,寻找新的可以满足x的机器 
    		{
    			p++;
    			c[a[p].y]++; 
    		}
    		for(int j=b[i].y;j<=100;j++)//在满足x的机器里,寻找满足y的 
    		{
    			if(c[j])
    			{
    				cnt++;
    				c[j]--;//记得去掉 
    				ans+=b[i].x*500+b[i].y*2;
    				break;//找到第一个就退出,因为要贪心地取y最小的 
    			}
    		}
    	}
    	printf("%d %lld",cnt,ans);
    	return 0;
    }
    
    • 1

    信息

    ID
    10088
    时间
    1000ms
    内存
    512MiB
    难度
    3
    标签
    递交数
    0
    已通过
    0
    上传者