正题
题目链接:https://jzoj.net/senior/#contest/show/2930/3
题目大意
一个平面直角坐标系上有nnn个点,如果两个点之间斜率在−1∼1-1\sim 1−1∼1之间那么就可以连接,求最少多少条折线可以连接这些点。
解题思路
我们将整个坐标系逆时针选择45∘(45^{\circ}(45∘(变为(x+y,y−x)(x+y,y-x)(x+y,y−x)))),然后每个点可以连接的位置就变成了右上方的矩形。
我们将点按照横坐标排序,问题就变为了一个序列,至少可以拆成多少个多少个不降序列。就是导弹拦截的第二问,答案就是最长上升子序列的长度。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=31000;
struct node{int num,w;
}a[N];
int n,q[N],tail;
bool cmp(node x,node y)
{return (x.num==y.num)?x.w>y.w:x.num<y.num;}
int main()
{freopen("lam.in","r",stdin);freopen("lam.out","w",stdout);scanf("%d",&n);for(int i=1;i<=n;i++){int x,y; scanf("%d%d",&x,&y);a[i]=(node){x+y,y-x};}sort(a+1,a+1+n,cmp);q[++tail]=a[1].w;for(int i=2;i<=n;i++){if(a[i].w>q[tail]) q[++tail]=a[i].w;else{int z=lower_bound(q+1,q+1+tail,a[i].w)-q;q[z]=a[i].w;}}printf("%d",tail);
}