D题-小红的线段

思路 : 将点按:在直线上、在直线上侧、在直线下侧,分为3类,用set对点的序号进行存取,优先选择两侧的点进行连接,因为在直线上的点只要能连就会带来价值,但两侧的点要么和另一侧连,要么连接直线上的点才有价值。

#include<bits/stdc++.h>
using namespace std;

typedef set<int>::iterator it;

int n,k,b;

int main(){
  set<int> p1,p2,p3;
  
  cin>>n>>k>>b;
  for(int i=1;i<=2*n;i++){
    int x,y;
    cin>>x>>y;
    //判断点的类型
    int tp=y-k*x-b;
    if(tp>0){
      p1.insert(i);
    }else if(tp==0){
      p2.insert(i);
    }else{
      p3.insert(i);
    }
  }
  
  int t1=p1.size(),t2=p2.size(),t3=p3.size();
  it it1=p1.begin(),it2=p2.begin(),it3=p3.begin();
  
  //最多可得与直线有交点连线数
  cout<<min(t1,t3)+min(t2,abs(t1-t3))+(t2-abs(t1-t3)>0?t2-abs(t1-t3):0)/2<<'\n';
    
  while(it1!=p1.end()&&it3!=p3.end()){
    cout<<*it1++<<' '<<*it3++<<" Y\n";
  }
    
  while(it1!=p1.end()&&it2!=p2.end()){
    cout<<*it1++<<' '<<*it2++<<" Y\n";
  }
    
  while(it3!=p3.end()&&it2!=p2.end()){
    cout<<*it2++<<' '<<*it3++<<" Y\n";
  }
    
  while(it2!=p2.end()){
    cout<<*it2++<<' '<<*it2++<<" Y\n";
  }
    
  while(it1!=p1.end()){
    cout<<*it1++<<' '<<*it1++<<" N\n";
  }
    
  while(it3!=p3.end()){
    cout<<*it3++<<' '<<*it3++<<" N\n";
  }
}