zoukankan      html  css  js  c++  java
  • 【洛谷5939】[POI1998] 折线(坐标转化)

    点此看题面

    • 规定二维平面上的一条折线只能从左向右一笔画过去,且每段与(x)轴的夹角在([-45^circ,45^circ])范围内。
    • 给定(n)个点,求至少画多少条折线才能覆盖所有点。
    • (nle3 imes10^4)

    坐标转化

    考虑((x_A,y_A))连向((x_B,y_B))的折线((x_A<x_B))与(x)轴夹角在([-45^circ,45^circ])范围内的充要条件,转化成坐标关系就是:

    [-1le frac{y_B-y_A}{x_B-x_A}le 1Leftrightarrowegin{cases}y_A+x_Ale y_B+x_B,\y_A-x_Age y_B-x_Bend{cases} ]

    于是我们把一个点的坐标转化为((y+x,y-x)),然后按首先第一维升序、其次第二维降序排序,问题就变成原序列至少需要拆成多少个单调不上升序列。

    根据(Dilworth)定理,这个问题等价于求原序列的最长上升子序列长度。

    代码:(O(nlogn))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 30000
    using namespace std;
    int n,f[N+5];struct P {int x,y;I bool operator < (Con P& o) Con {return x^o.x?x<o.x:y>o.y;}}p[N+5];
    int main()
    {
    	RI i,x,y;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d%d",&x,&y),p[i]=(P){y+x,y-x};sort(p+1,p+n+1);//坐标转化+排序
    	RI t=0;for(i=1;i<=n;++i) f[t&&p[i].y<=f[t]?lower_bound(f+1,f+t+1,p[i].y)-f:++t]=p[i].y;return printf("%d
    ",t),0;//最长上升子序列
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    hdu 1203 I NEED A OFFER! (01背包)
    链式前向星
    hdu 3790 最短路问题 (spfa练手)
    hdu 2859 Phalanx (最大对称子矩阵)
    hdu 1160 FatMouse's Speed (最长上升子序列+打印路径)
    hdu 5289 Assignment (ST+二分)
    vue环境配置 vue-cli脚手架
    1、初始Java应用程序
    HTML5之Canvas画正方形
    布尔表达式
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu5939.html
Copyright © 2011-2022 走看看