Wrapping Chocolate(ABC 245 E)

AtCoder - abc245_e

题目大意

N块巧克力,第i块的宽度为Ai,长度为Bi,同时还有M个放巧克力的盒子,第i个盒子的宽度为Ci,长度为Di,定义第i块巧克力能被放进第j个盒子中当且仅当AiCi&&BiDi,每个盒子中只能放入一块巧克力,问这N块巧克力能不能都被放进盒子中。(1NM2×105,1Ai,Bi,Ci,Di109)

思路

首先肯定想到排序,但是如果是按照长和宽这两个性质,怎么排都感觉不能做。于是我们考虑把宽度当作第一关键字,当宽度相同,再盒子优先,这样我们就可以保证对于每一块巧克力,它之前的盒子一定是比他宽的,然后它要选择哪个盒子才能最优呢?很容易能想到就是选择在它之前的比它长且长的最少的那个盒子,这样这题差不多就完成了。但是还有一点就是如果一个个找就会显得有点naive,所以我们可以建一棵权值线段树,不过需要对Di进行离散化,然后查找的时候就可以区间查询+二分,修改的话单点修改就足够了,能想到这里这道题就能轻松AC啦!

代码

#include<bits/stdc++.h>
using namespace std;
int A[200005],B[200005],C[200005],D[200005];
struct node
{
    int x,y,ty;
    bool operator<(const node& b)const
    {
        if(x!=b.x)return x>b.x;
        return ty>b.ty;
    }
}a[400005];
int tree[200005<<2];
void update(int p,int l,int r,int w,int x)
{
    if(l==r)
    {
        tree[p]+=w;
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)update(p<<1,l,mid,w,x);
    else update(p<<1|1,mid+1,r,w,x);
    tree[p]=tree[p<<1]+tree[p<<1|1];
}
int query(int p,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)return tree[p];
    int ans=0;
    int mid=(l+r)>>1;
    if(x<=mid)ans+=query(p<<1,l,mid,x,y);
    if(mid<y)ans+=query(p<<1|1,mid+1,r,x,y);
    return ans;
}
int aa[200005];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&A[i]);
    for(int i=1;i<=n;i++)scanf("%d",&B[i]);
    for(int i=1;i<=m;i++)scanf("%d",&C[i]);
    for(int i=1;i<=m;i++)scanf("%d",&D[i]);
    for(int i=1;i<=n;i++)a[i]={A[i],B[i],1};
    for(int i=1;i<=m;i++)
    {
        a[i+n]={C[i],D[i],2};
        aa[i]=D[i];
    }
    sort(a+1,a+n+m+1);
    sort(aa+1,aa+m+1);
    int siz=unique(aa+1,aa+m+1)-aa-1;
    bool ck=1;
    for(int i=1;i<=n+m;i++)
    {
        if(a[i].ty==2)
        {
            int id=lower_bound(aa+1,aa+siz+1,a[i].y)-aa;
            update(1,1,siz,1,id);
        }
        else
        {
            int id=lower_bound(aa+1,aa+siz+1,a[i].y)-aa;
            int l=id,r=siz;
            while(l<r)
            {
                int mid=(l+r)>>1;
                if(query(1,1,siz,id,mid))r=mid;
                else l=mid+1;
            }
            if(query(1,1,siz,l,l))update(1,1,siz,-1,l);
            else {ck=0;break;}
        }
    }
    if(ck)printf("Yes\n");
    else printf("No\n");
    return 0;
}

__EOF__

本文作者Jerry-Black
本文链接https://www.cnblogs.com/Jerry-Black/p/16208170.html
关于博主:小蒟蒻一只( ̄^ ̄)ゞ
版权声明:转载请注明来源哟~ QAQ
声援博主:UP UP UP !!!
posted @   Jerry_Black  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示