您的位置:首页 > 其它

区间点覆盖 Case of Fugitive:CodeForces - 556D

2017-09-18 19:43 369 查看

题目:Case of Fugitive:CodeForces - 556D

题意

在一维坐标上,有N个小岛,每个位于坐标[li,ri](线段)。现在需要用M座桥连接这N个小岛.小岛i和i+1能够连接,当且仅当长度为a的桥能够架设在[x,y]的位置上,且li≤x≤ri,li+1≤y≤ri+1,y−x=a,每座桥只能使用一次。

数据范围

N,M≤2∗105

1≤li≤ri≤1018

1≤ai≤1018

思路

岛屿i与岛屿i+1能够连接,当且仅当桥的长度a位于区间[li+1−ri,ri+1−li]。把所有桥的长度值看做M个点,把需要的N-1座桥的可行长度看做线段,则问题转化为了:有N条线段以及M个点,是否能够保证每条线段上都落一个点?点能够落在线段上,当且仅当点的值位于线段的区间内。

显然对于每条线段,要用尽量短的桥去覆盖。

对于两条线段a,b。

1.若a,b不相交,则他们需要的桥互不影响,谁优先匹配都无所谓。

2.若a,b相交。不妨设ra≤rb

2.1 ra=rb 显然谁的l小,先匹配谁,比较合理。

2.2 ra<rb,la≤lb,显然在剩余的桥中,应该先选择满足条件的最短的桥去匹配a,再去匹配b。

2.3 ra<rb,la>lb,这时候应该先匹配a。

1.2 结合,我们可以得知,a,b线段的优先级是先比r再比l。有点贪心的感觉。

这题主要是要会用平衡树快速删除和查询桥。。。用STL写起来特别短..

代码

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define foreach(it, E) for(__typeof(E.begin()) it = E.begin(); it != E.end(); ++it)
// #define XDEBUG
typedef long long LL;
using namespace std;

const int MAX_N = 2e5 +3;
int N,M;
pair<pair<LL,LL>,int> line[MAX_N];
set<pair<LL,int>> brid;
int ans[MAX_N];

int main()
{
LL lf,rf,l,r;
scanf("%d%d%lld%lld",&N,&M,&lf,&rf);
for (int i=1; i<N; ++i,lf=l,rf=r){
scanf("%lld%lld",&l,&r);
line[i] = {{r-lf,l-rf},i};
}
rep(i,1,M){
LL tmp;
scanf("%lld",&tmp);
brid.insert({tmp,i});
}
sort(line+1,line+N);
rep(i,1,N-1){
auto iti = brid.lower_bound({line[i].first.second,1});
if(iti==brid.end() || iti->first>line[i].first.first) return printf("No\n"),0;
ans[line[i].second] = iti->second;
brid.erase(iti);
}
printf("Yes\n");
rep(i,1,N-1) printf("%d ", ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  区间点覆盖