【jzoj5329】【NOIP2017提高A组模拟8.22】【时间机器】【数据结构】【扫描线】

本文介绍了一种基于扫描线的机器匹配算法,通过将机器和电阻按照特定顺序排列,并使用set进行匹配,实现有效的资源分配。该算法适用于需要为机器寻找合适电阻的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

description

这里写图片描述

solution

把机器和电阻按l排序,l相等时电阻排前面,扫描线从左往右扫,遇到电阻把右端点放入set,遇到机器lowerbound找到最小的r比机器的r大匹配即可。

code

#include<set>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define fr(i,j) for(int i=begin[j];i;i=next[i])
using namespace std;
int const mn=1e5+9,inf=1e9+7;
int t,n,m;
struct rec{
    int l,r,s,op;
};
rec a[mn];
struct re2{
    int r,s;
    friend bool operator<(re2 x,re2 y){
        return (x.r<y.r)||((x.r==y.r)&&(x.s<y.s));
    }
    re2(int R,int S){
        r=R;s=S;
    }
};
multiset<re2>s;
bool cmp(rec x,rec y){
    return (x.l<y.l)||((x.l==y.l)&&(x.op>y.op));
}
int read(){
    char ch=getchar();
    while((ch<'0')||(ch>'9'))ch=getchar();
    int v=0;
    while((ch>='0')&&(ch<='9'))v=v*10+ch-'0',ch=getchar();
    return v;
}
int main(){
    freopen("machine.in","r",stdin);
    freopen("machine.out","w",stdout);
    scanf("%d",&t);
    fo(cas,1,t){
        scanf("%d%d",&n,&m);
        int tmp=0;
        fo(i,1,n){
            tmp++;
            a[tmp].l=read();
            a[tmp].r=read();
            a[tmp].s=read();
            a[tmp].op=-1;
        }
        fo(i,1,m){
            tmp++;
            a[tmp].l=read();
            a[tmp].r=read();
            a[tmp].s=read();
            a[tmp].op=1;
        }
        sort(a+1,a+tmp+1,cmp);
        int ok=1;
        s.clear();
        fo(i,1,tmp)if(a[i].op==1)
            s.insert(re2(a[i].r,a[i].s));
        else{
            while((a[i].s)&&(s.lower_bound(re2(a[i].r,0))!=s.end())){
                re2 tm2=*s.lower_bound(re2(a[i].r,0));
                s.erase(s.lower_bound(re2(a[i].r,0)));
                int tm3=min(a[i].s,tm2.s);
                a[i].s-=tm3;
                if(tm3!=tm2.s)s.insert(re2(tm2.r,tm2.s-tm3));
            }
            if(a[i].s){
                ok=0;
                break;
            }
        }
        if(ok)printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值