思路:变换一下坐标系新的坐标系就是给定的两条直线,变换之后求 x,y 都严格递增的点的个数的max;

求 x,y 都严格递增的点的个数的max,按照x的从小到大排序,x相同的按照y的从大到小排序然后对y的值进行LIS

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
typedef long long int LL;
const int INF=2e9+1e8;
const int SIZE =1e5+100; int n,a,b,c,d;
struct Point
{
double x,y;
};
Point point[SIZE];
double dp[SIZE];
struct StraightLine
{
double A,B,C;
};// 一条直线方程为: A*x + B*y + C=0
bool is_inside(Point p)
{
if(a*p.x<b*p.y&&d*p.y<c*p.x) return true;
if(a*p.x>b*p.y&&d*p.y>c*p.x) return true;
return false;
}
double dist(Point x,Point y)
{
return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*((x.y-y.y)));
}
Point GetPoint(StraightLine x,StraightLine y) //得到两直线的交点 前提有一个交点。
{
Point ans;
ans.y=(y.C*x.A-x.C*y.A)/(y.A*x.B-x.A*y.B);
ans.x=(y.C*x.B-x.C*y.B)/(x.A*y.B-y.A*x.B);
return ans;
}
Point change(Point p)
{
Point ans;
StraightLine x,y;
x.A=(double)a,x.B=(double)-b,x.C=0.;
y.A=(double)c,y.B=(double)-d,x.C=(p.y*b-p.x*a);
ans.x=dist(p,GetPoint(x,y));
x.A=(double)c,x.B=(double)-d,x.C=0.;
y.A=(double)a,y.B=(double)-b,x.C=(p.y*d-p.x*c);
ans.y=dist(p,GetPoint(x,y));
return ans;
}
bool cmp(Point x,Point y)
{
if(x.x==y.x)
return x.y>y.y;
else return x.x<y.x;
}
int LIS(vector<double>& v)
{
int counter=-1,len=(int)v.size();
for(int i=0; i<=len+1; i++)
dp[i]=1e20;
for(int i=0; i<len; i++)
{
int k=lower_bound(dp,dp+len,v[i])-dp;
dp[k]=v[i];
counter=max(k,counter);
}
return counter+1;
}
int main()
{
int ncase;
cin>>ncase;
while(ncase--)
{
scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
int k=0;
while(n--)
{
Point temp;
scanf("%lf%lf",&temp.x,&temp.y);
if(is_inside(temp))
{
point[k++]=change(temp);
}
}
sort(point,point+k,cmp);
vector<double>num;
for(int i=0; i<k; i++)
num.push_back(point[i].y);
cout<<LIS(num)<<endl;
}
return 0;
}
05-11 23:01