COGS2085 Asm.Def的一秒

时间限制:1 s   内存限制:256 MB

【题目描述】

 

“你们搞的这个导弹啊,excited!”

Asm.Def通过数据链发送了算出的疑似目标位置,几分钟后,成群结队的巡航导弹从“无蛤”号头顶掠过,布满了天空。

“一共发射了多少导弹?”

“十亿美元。”斯科特·华莱士回答,“单价100万,现在天上有1000多枚。这玩意能自动搜索10个可疑点,找到目标就发动攻击。”

“什么?10个?我给了它10万个点!”

“这会让它的程序崩溃的。好在你还有时间手动输入路径。”

“多久?”

“零……还有一秒,他们又给续上了一秒。”

“我想静静,别问我静静是谁。”

Asm.Def在第一象限内找到了n个可疑点。他需要为导弹规划路径。

如图所示,导弹一开始在(0,0)。它只能朝着一定的方向——即严格夹在图中两条射线间的方向(白色部分)前进。注意,它不能沿着这两条射线前进,当然也不能停在原地。

当导弹到达某个可疑点后,它仍然只能朝着该范围内的方向前进,如图。

Asm.Def想要让导弹经过尽可能多的可疑点。他需要在一秒钟内知道,最多能经过多少个可疑点。

 

【输入格式】

 

第1行1个整数n。

第2行4个整数a b c d:代表两条射线的斜率分别是a/b和c/d。保证0<=a,b,c,d<=10^5,a/b<c/d(即a/b是靠下的那条射线),a/b≠0/0,c/d≠0/0.

接下来n行,每行2个整数xi,yi(1<=xi,yi<=10^5),代表i号可疑点的坐标。

 

【输出格式】

一行一个整数,即最多能经过几个可疑点。

【样例输入】

15
1 3 2 1
3 1
6 2
4 2
2 5
4 5
6 6
3 4
1 6
2 1
7 4
9 3
5 3
1 3
15 5
12 4

【样例输出】

4

【提示】

 

这是最佳路径。注意,导弹不能前往位于射线上的点。

对于30%的数据,n<=1000,a=0,b=1,c=1,d=0。

对于60%的数据,n<=1000。

对于100%的数据,n<=10^5。

 

数学问题 计算几何  动态规划 LIS

题面异常带感啊233

 

如果两条射线分别平行于x和y轴,显然是一个最长单调上升序列问题

现在两条射线角度不定,但只要以射线为x、y轴建立平面坐标系,把原坐标系上的点映射到新坐标系上,就又可以求LIS了

如何求新坐标?

过点作新坐标轴x的平行线,与另一坐标轴y交于点k,|(kx,ky)-(0,0)|即是其在新坐标轴y上的长度,用它除以新坐标轴y向量的单位长度,就是它的新y坐标。

x坐标同理

↑注意由于输入的是分数,一通约分之后可以得到整数坐标,不需要用double存←博主后知后觉

注意所求是单调上升而不是单调不降,所以x坐标相同的时候,要先更新y大的

 

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #define LL long long
 7 using namespace std;
 8 const int mxn=100010;
 9 int read(){
10     int x=0,f=1;char ch=getchar();
11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 struct point{
16     LL x,y;
17 /*    double x,y;
18     point operator + (point b){return (point){x+b.x,y+b.y};}
19     point operator - (point b){return (point){x-b.x,y-b.y};}
20     double operator * (point b){return x*b.x+y*b.y;}*/
21     bool operator < (point b)const{
22         return x<b.x || (x==b.x && y>b.y);
23     }
24 }a[mxn],T[3];
25 LL Cross(point a,point b){
26     return a.x*b.y-a.y*b.x;
27 }
28 int n,m;
29 int f[mxn],t[mxn];
30 void add(int x,int v){
31     while(x<=n){t[x]=max(t[x],v);x+=x&-x;}
32 }
33 int que(int x){
34     int res=0;
35     while(x){res=max(res,t[x]);x^=x&-x;}
36     return res;
37 }
38 LL bas[mxn];
39 int main(){
40     freopen("asm_second.in","r",stdin);
41     freopen("asm_second.out","w",stdout);
42     int i,j;point tmp;
43     n=read();
44     T[1].y=read();T[1].x=read();T[2].y=read();T[2].x=read();
45     for(i=1;i<=n;i++){
46         a[i].x=read();a[i].y=read();
47         tmp=(point){Cross(T[1],a[i]),Cross(a[i],T[2])};
48         //a[i].x*t[1].y-a[i].y*t[1].x
49         a[i]=tmp;
50     }
51     a[++n]=(point){0,0};
52     sort(a+1,a+n+1);
53     //
54     for(i=1;i<=n;i++)bas[i]=a[i].y;
55     sort(bas+1,bas+n+1);
56     int ed=unique(bas+1,bas+n+1)-bas-1;
57     for(i=1;i<=n;i++){
58         if(a[i].y<0)a[i].y=-1;
59         else a[i].y=lower_bound(bas+1,bas+ed+1,a[i].y)-bas-1;
60     }
61     int ans=0;
62     for(i=1;i<=n;i++){
63 //        printf("i:%d %lld %lld\n",i,a[i].x,a[i].y);
64         if(a[i].x<=0 || a[i].y<=0)continue;
65         int res=que(a[i].y-1);
66         f[i]=max(f[i],res+1);
67         add(a[i].y,f[i]);
68         ans=max(ans,f[i]);
69     }
70     printf("%d\n",ans);
71     return 0;
72 }

 

posted @ 2017-04-05 09:13  SilverNebula  阅读(229)  评论(0编辑  收藏  举报
AmazingCounters.com