题目背景:
幻想乡的创始人之一,八云紫,有着强大的控制结界的能力,可以瞬间消除一定范围内所有弹幕。我们可以将其消除范围视为一个矩形,而弹幕可以视为动点。
八云紫想要嘲讽她的敌人,所以她希望只使用一次消除能力,尽可能多地消除弹幕。
请你告诉她,在哪一时刻使用道具,可以消除尽可能多的弹幕。
问题描述:
在平面上给定一个矩形区域(也可能退化成线段或者点)。
矩形的边与坐标轴平行,左下端点为 (xl,yl),右上端点为 (xr,yr)。
给定 n 个动点,初始坐标为 (xi, yi),运动方向为 (ui,vi),速度为 sqrt((ui)^2+(vi)^2)
求在哪一时刻 t (t ∈ N),在矩形内部及边界的动点数目最多。
如果有多个 t 满足条件,输出最小的 t 即可。
输入格式:
第一行 5 个正整数,n, xl, yl, xr, yr,表示动点个数和矩形区域。
接下来 n 行,每行 4 个整数,xi, yi, ui, vi ,描述第 i 个动点。
输出格式:
在矩形内部及边界的动点数目最多的时刻 t (t ∈ N)。
如果有多个 t 满足条件,输出最小的 t 即可。
题解:
预处理之后 对时间差分
点只会与矩形框内两次(端点视为两次 便于处理)
那么进入时间a影响到的点就是ceil(a)
出去时间b影响到的点就是floor(b)+1
将时间离散化(整数)
然后就可以O(n)求解
细节什么的很麻烦
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=100000+10;
double x[maxn],y[maxn],u[maxn],v[maxn];
int t[maxn],z[maxn];
int B[maxn*2];
int hash[maxn*2];
int tot,sz1,sz2,tt;
double xx,yy,uu,vv;
inline int bs(int x){
int l=1,r=tot;
while(l+1<r){
int mid=(l+r)>>1;
if(hash[mid]>=x)
r=mid;
else l=mid+1;
}
if(hash[l]==x)
return l;
return r;
}
int main(){
freopen("camera.in","r",stdin);
freopen("camera.out","w",stdout);
int n;
scanf("%d %lf %lf %lf %lf",&n,&xx,&yy,&uu,&vv);
for(int i=1;i<=n;i++){
scanf("%lf %lf %lf %lf",&x[i],&y[i],&u[i],&v[i]);
if(x[i]>=xx&&x[i]<=uu&&y[i]>=yy&&y[i]<=vv){
t[++sz1]=0;
if(u[i]==0){
double a=(vv-y[i])/v[i];
double b=(yy-y[i])/v[i];
if(a>0)
z[++sz2]=int(floor(a))+1;
else z[++sz2]=int(floor(b))+1;
}
else if(v[i]==0){
double a=(uu-x[i])/u[i];
double b=(xx-x[i])/u[i];
if(a>0)
z[++sz2]=int(floor(a))+1;
else z[++sz2]=int(floor(b))+1;
}
else {
double a=(uu-x[i])/u[i];
double b=(xx-x[i])/u[i];
double c=(vv-y[i])/v[i];
double d=(yy-y[i])/v[i];
double p,q;
if(a>0)
p=a;
else p=b;
if(c>0)
q=c;
else q=d;
z[++sz2]=int(floor(min(p,q)))+1;
}
continue;
}
if(u[i]==0){
if(x[i]>=xx&&x[i]<=uu){
double a=(yy-y[i])/v[i];
double b=(vv-y[i])/v[i];
if(a>b)
swap(a,b);
if(a>=0)
t[++sz1]=int(ceil(a));
if(b>=0)
z[++sz2]=int(floor(b))+1;
}
}
else if(v[i]==0){
if(y[i]>=yy&&y[i]<=vv){
double a=(xx-x[i])/u[i];
double b=(uu-x[i])/u[i];
if(a>b)
swap(a,b);
if(a>=0)
t[++sz1]=int(ceil(a));
if(b>=0)
z[++sz2]=int(floor(b))+1;
}
}
else {
double k=v[i]/u[i];
double b=y[i]-x[i]*k;
double tl=k*xx+b;
double p,q;
int ph=0,qh=0;
if(tl>=yy&&tl<=vv){
if((xx-x[i])/u[i]>=0){
if(!ph){
p=(xx-x[i])/u[i];
ph=1;
}
else if(!qh){
qh=1;
q=(xx-x[i])/u[i];
}
}
}
tl=k*uu+b;
if(tl>=yy&&tl<=vv){
if((uu-x[i])/u[i]>=0){
if(!ph){
p=(uu-x[i])/u[i];
ph=1;
}
else if(!qh){
qh=1;
q=(uu-x[i])/u[i];
}
}
}
tl=(yy-b)/k;
if(tl>=xx&&tl<=uu){
if((yy-y[i])/v[i]>=0){
if(!ph){
p=(yy-y[i])/v[i];
ph=1;
}
else if(!qh){
qh=1;
q=(yy-y[i])/v[i];
}
}
}
tl=(vv-b)/k;
if(tl>=xx&&tl<=uu){
if((vv-y[i])/v[i]>=0){
if(!ph){
p=(vv-y[i])/v[i];
ph=1;
}
else if(!qh){
qh=1;
q=(vv-y[i])/v[i];
}
}
}
if(q<p)
swap(q,p);
t[++sz1]=int(ceil(p));
z[++sz2]=int(floor(q))+1;
}
}
for(int i=1;i<=sz1;i++)
B[++tt]=t[i];
for(int i=1;i<=sz2;i++)
B[++tt]=z[i];
sort(B+1,B+tt+1);
hash[++tot]=B[1];
for(int i=2;i<=tt;i++)
if(B[i]!=B[i-1])
hash[++tot]=B[i];
memset(B,0,sizeof(B));
for(int i=1;i<=sz1;i++){
int q=bs(t[i]);
B[q]++;
}
for(int i=1;i<=sz2;i++){
int q=bs(z[i]);
B[q]--;
}
int ans=0,tim;
for(int i=1;i<=tot;i++){
B[i]+=B[i-1];
if(B[i]>ans){
ans=B[i];
tim=hash[i];
}
else if(B[i]==ans&&hash[i]<=tim){
ans=B[i];
tim=hash[i];
}
}
printf("%d\n",tim);
return 0;
}