P2554 - 【2017杭二联考】穿越矩形
Description
题目背景:
幻想乡的创始人之一,八云紫,有着强大的控制结界的能力,可以瞬间消除一定范围内 所有弹幕。我们可以将其消除范围视为一个矩形,而弹幕可以视为动点。
八云紫想要嘲讽她的敌人,所以她希望只使用一次消除能力,尽可能多地消除弹幕。
请你告诉她,在哪一时刻使用道具,可以消除尽可能多的弹幕。
问题描述:
在平面上给定一个矩形区域(也可能退化成线段或者点)。 矩形的边与坐标轴平行,左下端 点为 (xl,yl),右上端点为 (xr,yr)。
给定 n 个动点,初始坐标为 (xi, yi),运动方向为 (ui,vi),速度为 sqrt((ui)2+(vi)2)sqrt((ui)2+(vi)2) 求在哪一时刻 t ( t ∈N ),在矩形内部及边界的动点数目最多。
如果有多个 t 满足条件,输出最小的 t 即可。
Input
第一行 5 个正整数,n, xl, yl, xr, yr,表示动点个数和矩形区域。
接下来 n 行,每行 4 个整数,xi, yi, ui, vi ,描述第 i 个动点。
Output
在矩形内部及边界的动点数目最多的时刻 t ( t ∈N )。
如果有多个 t 满足条件,输出最小的 t 即可。
Sample Input
2 2 2 3 3
3 1 -1 1
2 3 1 -1
Sample Output
1
Hint
数据范围:
对于前 40% 数据, 1<= n <= 100, 1 <= xl, xr, yl, yr, xi, yi <= 100, -10 <= ui, vi <= 10
对于 100% 数据,1<= n <= 10^5, 1 <= xl, xr, yl, yr, xi, yi <= 10^9, 0 <= |ui|, |vi|<= 10^5, xl <= xr, yl <= yr
保证 n,xl,xr,yl,yr,xi,yi,ui,vi 均为整数.
Source
数学,计算几何
考试时看错题目了,以为方向指的是从原点向给出的 (ui,vi)走(我以为是一个坐标),然后就GG了。。。
首先明确(ui,vi)是一个向量,由于速度是sqrt((ui)2+(vi)2)sqrt((ui)2+(vi)2),向量分解一下就是横坐标+u,纵坐标+v,然后模拟每一秒的运动情况,再判断,就可获得40分。(详见work()函数)
一百分的做法呢?我们发现其实只要知道在哪一个时间段内点在矩形上或中就可以了。我们预处理出每个点在矩形内部的时间(用临界点计算),再将时间离散化,将每个点的时间差分,最后o(n)取最大即可。
交了一发WA了,90分,不知道错了哪里。。。发现是小数据WA了,就可耻的加了个work()暴力程序去算。。。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #include<algorithm> 7 #include<vector> 8 #include<stack> 9 #include<queue> 10 #include<map> 11 #define RG register 12 #define IL inline 13 #define pi acos(-1.0) 14 #define ll long long 15 using namespace std; 16 struct point{ 17 int x,y,u,v; 18 }; 19 point a[100005]; 20 int n,xl,yl,xr,yr,cnt=0; 21 int in[100005],out[100005]; 22 int l[100005],r[100005]; 23 int F[200005],rak[200005]; 24 int c[200005]; 25 map <int,int> s; 26 void work(){ 27 int T=0,cnt=0,maxn=0; 28 for(int t=1; ;t++){ 29 int ans=0; 30 for(int j=1;j<=n;j++){ 31 a[j].x+=a[j].u; 32 a[j].y+=a[j].v;//分解向量 33 ++cnt; 34 if(a[j].x>=xl&&a[j].x<=xr&& a[j].y>=yl&& a[j].y<=yr) ++ans; 35 if(cnt>=10000000){ 36 printf("%d",T); 37 exit(0); 38 } 39 } 40 if(ans>maxn) maxn=ans,T=t; 41 if(cnt>=10000000){ 42 printf("%d",T); 43 exit(0); 44 } 45 } 46 } 47 int main() { 48 scanf("%d%d%d%d%d",&n,&xl,&yl,&xr,&yr); 49 for(int i=1;i<=n;i++) scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].u,&a[i].v); 50 if(n<=100) work(); 51 for(int i=1;i<=n;i++){ 52 int txl,txr,tyl,tyr; 53 if((a[i].u==0)&&(a[i].x<xl||a[i].x>xr)) continue; 54 if((a[i].v==0)&&(a[i].y<yl||a[i].y>yr)) continue;//不可能成立直接判断掉 55 if(a[i].u==0) txl=0,txr=999999999; 56 else{ 57 txl=(xl-a[i].x)%a[i].u==0?(xl-a[i].x)/a[i].u:(xl-a[i].x-1)/a[i].u+1; 58 txr=(xr-a[i].x)/a[i].u; 59 if(a[i].u<0) swap(txl,txr); 60 } 61 if(a[i].v==0) tyl=0,tyr=999999999; 62 else{ 63 tyl=(yl-a[i].y)%a[i].v==0?(yl-a[i].y)/a[i].v:(yl-a[i].y-1)/a[i].v+1; 64 tyr=(yr-a[i].y)/a[i].v; 65 if(a[i].v<0) swap(tyl,tyr); 66 } 67 if(txl<0) txl=0; if(txr<0) txr=-1; 68 if(tyl<0) tyl=0; if(tyr<0) tyr=-1; 69 int L=max(txl,tyl),R=min(txr,tyr); 70 if(L>R) continue; 71 ++cnt; 72 l[cnt]=L,r[cnt]=R; 73 } 74 for(int i=1;i<=cnt;i++) F[++F[0]]=l[i],F[++F[0]]=r[i]; 75 sort(F+1,F+F[0]+1); 76 int tep=0; 77 for(int i=1;i<=F[0];i++) 78 if(i==1||F[i]!=F[i-1]) s[F[i]]=++tep,rak[tep]=F[i]; 79 for(int i=1;i<=cnt;i++){ 80 c[s[l[i]]]++; 81 c[s[r[i]]+1]--; 82 } 83 int maxn=0,T=0,j=0; 84 for(int i=1;i<=tep;i++){ 85 j+=c[i]; 86 if(j>maxn) maxn=j,T=i; 87 } 88 printf("%d",rak[T]); 89 return 0; 90 }