CF555B Case of Fugitive
题目大意
有一些不相交线段和一些桥,桥可以架在两个相邻的线段上。求现有的桥是否可以使所有线段连通。
题解
在两个线段上架桥,桥的长度在一个范围内,相当于一个长度的区间,一个桥只有一个长度,相当于一个长度的点。这就转化成了点匹配区间问题。
点匹配区间问题我们在贪心(POJ3614)那里学了,把所有区间按照左端点从大到小排序,把点按照位置从大到小排序,每次总是把最右侧区间与在该区间内的最右端点匹配。问题是:如何满足可以随时删除点,且可以快速找到该区间内的最右端点呢?用key值为点的长度递减的multiset的delete和lower_bound函数可以轻松解决。注意delete时传的参数时迭代器(指针),而不是值,否则一删就把重合的点全删了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <vector> #include <set> using namespace std; const int MAX_LAND = 200010, MAX_BRIDGE = 200010; int TotLand, TotLenRange, TotBridge; int Ans[MAX_BRIDGE]; struct Bridge { long long Len; int OrgP; bool operator < ( const Bridge& a) const { return Len > a.Len; } }_bridges[MAX_BRIDGE]; struct Cmp { bool operator () ( const Bridge& a, const Bridge& b) { return a.Len < b.Len; } }; struct Land { long long L, R; bool operator < ( const Land& a) const { return L < a.L; } }_lands[MAX_LAND]; struct LenRange { long long L, R; int OrgL; bool operator < ( const LenRange& a) const { return L > a.L; } }_lenRanges[MAX_LAND]; void Read() { scanf ( "%d%d" , &TotLand, &TotBridge); TotLenRange = TotLand - 1; for ( int i = 1; i <= TotLand; i++) scanf ( "%lld%lld" , &_lands[i].L, &_lands[i].R); for ( int i = 1; i <= TotBridge; i++) scanf ( "%lld" , &_bridges[i].Len); } void Init() { for ( int i = 1; i <= TotBridge; i++) _bridges[i].OrgP = i; sort(_lands + 1, _lands + TotLand + 1); for ( int i = 1; i <= TotLand - 1; i++) { _lenRanges[i].L = _lands[i + 1].L - _lands[i].R; _lenRanges[i].R = _lands[i + 1].R - _lands[i].L; _lenRanges[i].OrgL = i; } sort(_lenRanges + 1, _lenRanges + TotLenRange + 1); } void Solve() { static multiset<Bridge> tree; for ( int i = 1; i <= TotBridge; i++) tree.insert(_bridges[i]); for ( int i = 1; i <= TotLenRange; i++) { Bridge temp; temp.Len = _lenRanges[i].R; multiset<Bridge>::iterator it = tree.lower_bound(temp); if (it == tree.end() || it->Len <_lenRanges[i].L ) { printf ( "No\n" ); return ; } Ans[_lenRanges[i].OrgL] = it->OrgP; tree.erase(it); } printf ( "Yes\n" ); for ( int i = 1; i <= TotLand - 1; i++) printf ( "%d " , Ans[i]); printf ( "\n" ); } int main() { Read(); Init(); Solve(); return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步