觉得可以用贪心做,开始想了下因为区间有两个端点,而且位置任意,有点不好处理。后来就想先以一个端点排序,以另一个端点作为贪心准则。首先对于所有的区间,我们按右端点递增排序。左端点不予考虑。并将所有的数(即桥长)递增排序。然后依次遍历每个区间,然后从剩下的数中找最小的可以满足这个区间的数去满足这个区间,如果找不到则直接输出No。其实就是把按从小到大顺序把桥与可以符合的区间中r最小的那个区间相匹配,这种贪心思路好理解一点,因为这样可以保证剩余的桥长度更大,剩余区间r也更大,而对于l显然长度更大的桥更好,符合贪心思想。
1 #include <cstdio> 2 #include <cstring> 3 #include <set> 4 #include <iostream> 5 #include <map> 6 #include <math.h> 7 #include <algorithm> 8 #include <vector> 9 using namespace std; 10 typedef long long ll; 11 const int N = 1000005; 12 const double pi= 3.14159265358979323846264; 13 14 int n,m,ans[200005]; 15 struct st{ 16 ll l,r; 17 int id; 18 19 }isa[200005]; 20 struct bge{ 21 ll len; 22 int id; 23 }bri[200005]; 24 bool cmp1(st a,st b){ 25 return a.r<b.r; 26 } 27 bool cmp2(bge a,bge b){ 28 return a.len<b.len; 29 } 30 multiset<bge>bridge;//这种set可以从中删除元素 31 32 bool operator < (bge b1, bge b2)//在multiset的排序中药用到的 33 { 34 return b1.len < b2.len; 35 } 36 bool solve(){ 37 bridge.clear(); 38 for(int i=1;i<=m;i++) 39 bridge.insert(bri[i]); 40 for(int i=1;i<n;i++){ 41 bge val; 42 val.len=isa[i].l; 43 set <bge>::iterator it = bridge.lower_bound(val);//找到bridge集合中第一个小于val.len的点 44 if((*it).len < isa[i].l || (*it).len > isa[i].r) //找不到任何可以满足当前区间的桥 45 { 46 printf("No "); 47 return false; 48 } 49 ans[isa[i].id] = (*it).id; //用找到的桥满足这个区间 50 bridge.erase(it); //删除当前找到的桥 51 52 } 53 return true; 54 } 55 int main() 56 { 57 freopen("in.txt","r",stdin); 58 cin>>n>>m; 59 int i; 60 ll pl,pr; 61 ll a,b; 62 for(i=1;i<=n;i++){ 63 scanf("%I64d%I64d",&a,&b); 64 if(i!=1){ 65 isa[i-1].id=i-1; 66 isa[i-1].l=a-pr; 67 isa[i-1].r=b-pl; 68 } 69 pl=a; 70 pr=b; 71 } 72 for(i=1;i<=m;i++){ 73 scanf("%I64d",&bri[i].len); 74 bri[i].id=i; 75 } 76 sort(isa+1,isa+n,cmp1); 77 sort(bri+1,bri+1+m,cmp2); 78 if(solve()){ 79 cout<<"Yes"<<endl; 80 for(i=1;i<n-1;i++) 81 printf("%d ",ans[i]); 82 printf("%d ",ans[n-1]); 83 } 84 return 0; 85 }