链接:https://ac.nowcoder.com/acm/contest/3005/I
来源:牛客网
天上有n颗星星,每颗星星有二维坐标(xi,yi)(x_i, y_i)(xi,yi),还有一个属性值ziz_izi,若两颗星星A, B满足xA<xBx_A < x_BxA<xB且yA<yBy_A < y_ByA<yB且zA<zBz_A < z_BzA<zB,则这两颗星星可以配成一对,每颗星星最多只能在一对之中,求最多能配成多少对星星。
思路:贪心思想;
我们先按x从小到大排序,如果x相等,就按y从大到小;
然后接下来遍历数组;
遇到z值为0的就放进容器;遇到1的就去寻找容器中小于此数的y值且在容器中y最大的那个数进行匹配;然后将这个数删除
不断重复这个过程即可
证明:作者:nocriz
链接:https://ac.nowcoder.com/discuss/365889
来源:牛客网
假设最优方案中排序后Z=1Z = 1Z=1的第 1 个没有按贪心策略匹配的点 iii ,在设 iii 在Z=0Z = 0Z=0中它能匹配的 yyy 最大的点为 jjj,如果 jjj 被点 kkk 匹配了,有两种情况:
- 原先 iii 没有和任何匹配,则直接去掉 kkk 的匹配,将 iii 和 jjj 匹配。
- 原先 iii 和 mmm 匹配,则将 kkk 改成和 mmm 匹配,将 iii 和 jjj 匹配,由于Yj>YmY_j>Y_mYj>Ym, 这样的匹配一定是成立的。并且修改后的匹配数不会变少,因此按照该贪心策略可以得到最优解。
-
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=3e5+10; 5 struct node{ 6 int a,b,c; 7 }p[maxn]; 8 int n; 9 bool cmp(node x,node y) 10 { 11 if(x.a==y.a) return x.b>y.b; 12 else return x.a<y.a; 13 } 14 int main() 15 { 16 cin>>n; 17 for( int i=0;i<n;i++ ) cin>>p[i].a>>p[i].b>>p[i].c; 18 sort(p,p+n,cmp); 19 multiset<int> pool; 20 int ans=0; 21 for( int i=0;i<n;i++ ){ 22 if( p[i].c ){ 23 multiset<int>::iterator it; 24 it=pool.lower_bound( p[i].b ); 25 if( it!=pool.begin() ){ 26 --it; 27 pool.erase(it); 28 ans++; 29 } 30 } 31 else pool.insert( p[i].b ); 32 } 33 cout<<ans<<endl; 34 return 0; 35 }