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 }