Gym 101606L - Lounge Lizards - [計算幾何+LIS]

題目連接:https://codeforces.com/gym/101606/problem/Lc++

 

題解:spa

在同一條線上的全部蜥蜴,他們的斜率都是相通的,換句話說能夠直接經過斜率將蜥蜴分組。code

每一組即表明一條直線上的全部蜥蜴,再將這條直線以TV點爲分界分紅兩條射線,這樣每條射線上的蜥蜴,按距離TV從近到遠,它們的身高排成一個整數序列,對這個序列求最長上升子序列便可。blog

須要注意的:ci

  DP求LIS的話是 $O(n^2)$ 的時間複雜度,是過不了的應該,要用貪心+二分 $O(n \log n)$ 求LIS長度;get

  不肯定直接用double類型存斜率是否是會有精度問題,能夠用pair<int,int>類型當作分數類來表示斜率,注意約分就行了,還能夠省去考慮直線平行座標軸的問題。it

 

AC代碼:class

#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;
}
相關文章
相關標籤/搜索