【BZOJ】2924: [Poi1998]Flat broken lines

题意

平面上有\(n\)个点,如果两个点的线段与\(x\)轴的角在\([-45^{\circ}, 45^{\circ}]\),则两个点可以连线。求最少的折线(折线由线段首尾相连)使得覆盖所有点。

分析

bzoj的题面有坑,不是15而是45。
将点绕原点旋转\(-45^{\circ}\)后,能连线的话就是另一个点在左上角。那么问题就是求最少链个数。根据定理,最少链个数=最大反链长度。

题解

用bit求最大反链即可。

#include <bits/stdc++.h>
using namespace std;
inline int getint() {
    int x=0, f=1, c=getchar();
    for(; c<48||c>57; f=c=='-'?-1:f, c=getchar());
    for(; c>47&&c<58; x=x*10+c-48, c=getchar());
    return x*f;
}
const int N=30005;
struct ip {
    int x, y;
    void scan() {
        int a=getint(), b=getint();
        x=a-b, y=-(a+b);
    }
}p[N];
inline bool cmpy(const ip &a, const ip &b) {
    return a.y<b.y;
}
inline bool cmpx(const ip &a, const ip &b) {
    return a.x==b.x?a.y>b.y:a.x<b.x;
}
int tot, n, s[N];
inline void upd(int x, int g) {
    for(; x<=tot; x+=x&-x) {
        s[x]=max(s[x], g);
    }
}
inline int sum(int x) {
    int y=0;
    for(; x; x-=x&-x) {
        y=max(y, s[x]);
    }
    return y;
}
int main() {
    n=getint();
    for(int i=1; i<=n; ++i) {
        p[i].scan();
    }
    sort(p+1, p+1+n, cmpy);
    for(int i=1, now=-100001; i<=n; ++i) {
        p[i].y==now?(p[i].y=tot):(now=p[i].y, p[i].y=++tot);
    }
    sort(p+1, p+1+n, cmpx);
    int ans=0;
    for(int i=1; i<=n; ++i) {
        int d=sum(p[i].y-1)+1;
        upd(p[i].y, d);
        ans=max(ans, d);
    }
    printf("%d\n", ans);
    return 0;
}

转载于:https://www.cnblogs.com/iwtwiioi/p/4985800.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值