Gym 101606L - Lounge Lizards - [计算几何+LIS]
题目链接:https://codeforces.com/gym/101606/problem/L
题解:
在同一条线上的所有蜥蜴,他们的斜率都是相通的,换句话说可以直接通过斜率将蜥蜴分组。
每一组即代表一条直线上的所有蜥蜴,再将这条直线以TV点为分界分成两条射线,这样每条射线上的蜥蜴,按距离TV从近到远,它们的身高排成一个整数序列,对这个序列求最长上升子序列即可。
需要注意的:
DP求LIS的话是 $O(n^2)$ 的时间复杂度,是过不了的应该,要用贪心+二分 $O(n \log n)$ 求LIS长度;
不确定直接用double类型存斜率是不是会有精度问题,可以用pair<int,int>类型当做分数类来表示斜率,注意约分就好了,还可以省去考虑直线平行坐标轴的问题。
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int maxn=1e6+10; int n,X,Y; int tot; map<pii,int> mp; struct Li { ll dist; int h; bool operator<(const Li& o)const { return dist<o.dist; } }; vector<Li> H[2][maxn]; inline pii grad(int x,int y) { int dx=x-X, dy=y-Y; int g=__gcd(dx,dy); return make_pair(dx/g,dy/g); } inline ll dist(ll x,ll y) { return (x-X)*(x-X)+(y-Y)*(y-Y); } inline bool check(int x,int y) { if(x==X) return y>Y; else return x>X; } int S[maxn],top; int solve(const vector<Li>& a) { S[top=0]=a[0].h; for(int i=1;i<a.size();i++) { int pos=lower_bound(S,S+top+1,a[i].h)-S; S[pos]=a[i].h; top=max(top,pos); } return top+1; } int main() { cin>>X>>Y; cin>>n; mp.clear(), tot=0; for(int i=1,x,y,h;i<=n;i++) { scanf("%d%d%d",&x,&y,&h); pii g=grad(x,y); if(mp[g]==0) mp[g]=++tot; H[check(x,y)][mp[g]].push_back((Li){dist(x,y),h}); } int ans=0; for(int i=1;i<=tot;i++) { sort(H[0][i].begin(),H[0][i].end()); sort(H[1][i].begin(),H[1][i].end()); if(H[0][i].size()) ans+=solve(H[0][i]); if(H[1][i].size()) ans+=solve(H[1][i]); } cout<<ans<<endl; }
转载请注明出处:https://dilthey.cnblogs.com/