题目连接:
http://codeforces.com/problemset/problem/555/B
题目大意:
有n个岛屿(岛屿在一列上,可以看做是线性的,用来描述岛屿位置的是起点与终点),m个桥,给出每个岛屿的位置和桥的长度,问是否可以把n个岛屿连起来?
解题思路:
排序+贪心,对于n个岛屿,相邻的两个之间起点和端点可以转化为n-1个连接桥的长度区间,把区间升序排列。
对于m个桥升序排列,对于每一个桥枚举每个可以合法覆盖的区间,选取最优的,选取的时候满足L<bridge_length<R,L经是有序的了。我们只需选取R最小的那个,因为R越大,这个区间就能适应更多的桥。
本宝宝对于选取最优区间的时候采用了优先队列,并不是最优的处理方式,大家有好的办法可以留言告诉弱弱。
1 #include <algorithm> 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cmath> 7 #include <queue> 8 using namespace std; 9 10 const int maxn = 200010; 11 #define LL __int64 12 struct bridge 13 { 14 LL val, id; 15 bool operator < (const bridge &a) const 16 { 17 return val < a.val; 18 } 19 } Bri[maxn]; 20 21 struct island 22 { 23 LL r, l, id; 24 bool operator < (const island &a) const 25 { 26 return l < a.l; 27 } 28 } Is[maxn]; 29 struct node 30 { 31 LL s, id; 32 bool operator < (const node &a) const 33 { 34 return s > a.s; 35 } 36 }; 37 38 LL vis[maxn], n, m; 39 bool solve () 40 { 41 priority_queue <node>Q;//当前桥可以搭建成功的区间 42 int l=0; 43 memset (vis, 0, sizeof(vis)); 44 45 for (int i=0; i<m; i++)//对于每个桥选取最优的区间搭建 46 { 47 node nu; 48 while (!Q.empty()) 49 { 50 nu = Q.top(); 51 if (nu.s < Bri[i].val) 52 Q.pop();//删除队列中的不合法区间 53 else 54 break; 55 } 56 57 while (Bri[i].val>=Is[l].l && Is[l].r >= Bri[i].val && l<n-1) 58 { 59 nu.id = Is[l].id; 60 nu.s = Is[l].r; 61 Q.push (nu);//区间加进队列 62 l ++; 63 } 64 if (Q.empty()) 65 continue;//没有合适的边,就继续循环加边 66 nu = Q.top (); 67 vis[nu.id] = Bri[i].id;//记录连接区间所对应的边 68 Q.pop(); 69 } 70 for (int i=1; i<n; i++) 71 if (!vis[i]) 72 return false; 73 return true;//所有区间都对应有边 74 } 75 int main () 76 { 77 while (scanf ("%I64d %I64d", &n, &m) != EOF) 78 { 79 island pre, cur; 80 LL i; 81 scanf ("%I64d %I64d", &pre.l, &pre.r); 82 for (i=1; i<n; i++) 83 { 84 scanf ("%I64d %I64d", &cur.l, &cur.r); 85 Is[i-1].id = i; 86 Is[i-1].l = cur.l - pre.r; 87 Is[i-1].r = cur.r - pre.l; 88 pre = cur; 89 } 90 for (i=0; i<m; i++) 91 { 92 Bri[i].id = i+1; 93 scanf ("%I64d", &Bri[i].val); 94 } 95 sort (Is, Is+n-1); 96 sort (Bri, Bri+m); 97 if (solve ()) 98 { 99 printf ("Yes\n"); 100 for (i=1; i<n-1; i++) 101 printf ("%I64d ", vis[i]); 102 printf ("%I64d\n", vis[i]); 103 } 104 else 105 printf ("No\n"); 106 } 107 return 0; 108 }