版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011528035/article/details/72729462
题意:一条线上有个n个大陆,范围给定且不相交,现在要邻近的大陆搭n-1座桥(桥的两段要在大陆上),给你m座桥的长度,问你怎么分配?
思路:其实就是n-1个区间和m个数,从m个数里面挑n-1个数一一对应区间,这个要求不小于左区间,不大于右区间。
先对区间的左区间排序,从假设从1开始走,如果遇到左区间就塞入区间,如果遇到超出区间范围就剔除(就是没有匹配到,输出no了),但是如果遇到桥长度就剔除右区间最小的(优先队列),这样有利于匹配(贪心),最后输出答案。
数据范围大,先离散化。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
#define LL long long
#define maxn 200005
struct node
{
LL l;
LL r;
int id;
bool operator <(node a) const { return r > a.r; }
};
priority_queue<node> q;
struct edge
{
LL l;
int id;
};
node rr[maxn];
edge e[maxn];
int ans[maxn];
LL c[maxn*3];
int cnt;
int cmp1(node a,node b)
{
return a.l<b.l;
}
int cmp2(edge a,edge b)
{
return a.l<b.l;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
LL l1,r1,l2,r2;
scanf("%lld%lld",&l1,&r1);
for(int i=1;i<n;i++)
{
scanf("%lld%lld",&l2,&r2);
rr[i].id=i;
rr[i].l=l2-r1;
rr[i].r=r2-l1;
l1=l2;
r1=r2;
c[++cnt]=rr[i].l;
c[++cnt]=rr[i].r;
}
sort(rr+1,rr+n,cmp1);
for(int i=1;i<=m;i++)
{
scanf("%lld",&e[i].l);
e[i].id=i;
c[++cnt]=e[i].l;
}
sort(e+1,e+m+1,cmp2);
sort(c+1,c+cnt+1);
int x=1,y=1;
for(int i=1;i<=cnt;i++)
{
if(c[i]==c[i-1])continue;
while(x<=n-1&&rr[x].l==c[i])
q.push(rr[x++]);
while(y<=m&&e[y].l==c[i])
{
if(!q.empty())
{
node f=q.top();
q.pop();
ans[f.id]=e[y++].id;
}
else
y++;
}
while(!q.empty())
{
node f=q.top();
if(f.r==c[i])
{
printf("No\n");
return 0;
}
else
break;
}
}
printf("Yes\n");
for(int i=1;i<n;i++)
printf("%d ",ans[i]);
return 0;
}