Description
给出二维空间 个点及其权值,问从起点开始,各个方向的射线上的点构成的序列的严格最长上升子序列长度之和
Input
首先输入两个整数 表示起点坐标,然后输入一整数 表示点数,之后 行每行三个整数 表示第 个点的坐标和权值
Output
输出各个方向上严格最长上升子序列长度之和
Sample Input
50 50
2
60 50 1
65 50 2
Sample Output
2
Solution
把每个方向上的点按其离起点距离排序,对排序后这些点的权值序列求 累加即可
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
typedef pair<ll,int>PP;
const int INF=0x3f3f3f3f,maxn=1000005;
map<P,int>m;
int xx,yy,n,res,cnt,a[maxn],dp[maxn];
vector<PP>g[maxn];
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
ll dis(int x,int y)
{
return (ll)x*x+(ll)y*y;
}
void deal(int x,int y,int h)
{
ll d=dis(x,y);
if(x==0)y/=abs(y);
else if(y==0)x/=abs(x);
else
{
int z=gcd(abs(x),abs(y));
x/=z,y/=z;
}
if(m.find(P(x,y))==m.end())m[P(x,y)]=++res;
g[m[P(x,y)]].push_back(PP(d,h));
}
int Solve(int n,int *a)
{
for(int i=1;i<n;i++)dp[i]=INF;
dp[0]=a[0];
int len=1;
for(int i=1;i<n;i++)
{
if(a[i]>dp[len-1])
dp[len++]=a[i];
else
dp[lower_bound(dp,dp+n,a[i])-dp]=a[i];
}
return len;
}
int main()
{
scanf("%d%d",&xx,&yy);
scanf("%d",&n);
res=0;
for(int i=1;i<=n;i++)
{
int x,y,h;
scanf("%d%d%d",&x,&y,&h);
x-=xx,y-=yy;
deal(x,y,h);
}
int ans=0;
for(int i=1;i<=res;i++)
{
sort(g[i].begin(),g[i].end());
cnt=g[i].size();
for(int j=0;j<cnt;j++)a[j]=g[i][j].second;
ans+=Solve(cnt,a);
}
printf("%d\n",ans);
return 0;
}