codeforces #310 div1 B

我们考虑n-1座桥每座桥需要的长度在一个区间[L,R]中

之后我们现在有m座桥,每个桥的长度为k

题意就是要求一个匹配方案

显然如果数据范围不大直接KM就可以了

可是20w的数据KM显然要T

所以我们考虑这是个区间问题,我们可以贪心

考虑两座桥A,B, A的区间被B的区间所包含

那么优先考虑A总比优先考虑B优

所以我们可以将区间按右端点从小到大排序,这样被包含的区间永远是优先考虑的

之后我们考虑选哪个点与当前区间匹配

这个时候可以考虑当前的决策对后面的影响

如果后面的区间包含当前区间,那么无论怎样决策都会使后面区间可选点-1

如果后面的区间不包含当前区间,那么选尽可能靠左的可行点对后面区间的影响最小

所以我们对于每个区间选可行的最靠左的点与之匹配,用set维护即可

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<set>
using namespace std;

typedef long long LL;
const int maxn=200010;
int n,m;
LL A[maxn],B[maxn];
struct Segment{
	LL L,R;
	int id;
}t[maxn];
struct bridge{
	LL len;
	int id;
}c[maxn];
int ans[maxn];
set<pair<LL,int> >S;
bool cmp(const Segment &A,const Segment &B){
	if(A.R==B.R)return A.L>B.L;
	return A.R<B.R;
}

int main(){
	scanf("%d%d",&n,&m);
	if(m<n-1){printf("No
");return 0;}
	for(int i=1;i<=n;++i){
		scanf("%I64d%I64d",&A[i],&B[i]);
		if(i>1){t[i-1].L=A[i]-B[i-1],t[i-1].R=B[i]-A[i-1],t[i-1].id=i-1;}
	}
	for(int i=1;i<=m;++i){
		scanf("%I64d",&c[i].len);
		c[i].id=i;
		S.insert(make_pair(c[i].len,c[i].id));
	}
	sort(t+1,t+n,cmp);
	for(int i=1;i<n;++i){
		pair<LL,int>p=*S.lower_bound(make_pair(t[i].L,-1));
		if(p.first<t[i].L){printf("No
");return 0;}
		if(p.first>t[i].R){printf("No
");return 0;}
		else ans[t[i].id]=p.second;
		S.erase(p);
	}
	printf("Yes
");
	for(int i=1;i<n;++i)printf("%d ",ans[i]);
	return 0;
	
}

  

原文地址:https://www.cnblogs.com/joyouth/p/5368492.html