1995. Yukari

★★☆   输入文件:camera.in   输出文件:camera.out   简单对比
时间限制:1 s   内存限制:128 MB

题目背景:

       幻想乡的创始人之一,八云紫,有着强大的控制结界的能力,可以瞬间消除一定范围内所有弹幕。我们可以将其消除范围视为一个矩形,而弹幕可以视为动点。

       八云紫想要嘲讽她的敌人,所以她希望只使用一次消除能力,尽可能多地消除弹幕。

       请你告诉她,在哪一时刻使用道具,可以消除尽可能多的弹幕。

 

 

问题描述:

       在平面上给定一个矩形区域(也可能退化成线段或者点)。

       矩形的边与坐标轴平行,左下端点为 (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 即可。

 

 

 

 

样例数据1:

camera.in

camera.out

2 2 2 3 3

3 1 -1 1

2 3 1 -1

1

 

样例数据2:

camera.in

camera.out

13 44 68 49 73

40 46 2 6

28 75 4 -1

32 61 3 3

41 64 2 1

40 99 2 -7

54 49 -2 6

32 80 4 -2

73 99 -7 -7

23 93 6 -5

44 96 0 -6

36 70 3 0

70 98 -6 -7

75 53 -7 4

4

 

 

数据范围:

       对于前 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 均为整数.

Cogs 1995. Yukari_#includeCogs 1995. Yukari_离散化_02
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 1000010
using namespace std;
int n,xl,yl,xr,yr;
int tot,cnt,sum[maxn],cnt1;
double l[maxn],r[maxn],h[maxn*2],h1[maxn*2];
int find(int x){
    int l=1,r=cnt,res=0;
    while(l<=r){
        int mid=(l+r)>>1;
        if(h[mid]<=x)res=mid,l=mid+1;
        else r=mid-1;
    }
    return res;
}
int main(){
    //freopen("camera.in","r",stdin);freopen("camera.out","w",stdout);
    freopen("Cola.txt","r",stdin);
    scanf("%d%d%d%d%d",&n,&xl,&yl,&xr,&yr);
    int x,y,u,v;
    int t1,t2,sx1,sx2,sy1,sy2;
    memset(r,127,sizeof(r));
    for(int i=1;i<=n;i++){
        scanf("%d%d%d%d",&x,&y,&u,&v);
        if((x<xl&&u<=0)||(x>xr&&u>=0)||(y<yl&&v<=0)||(y>yr&&v>=0))continue;
        tot++;
        if(x<=xr&&x>=xl&&y<=yr&&y>=yl){
            l[tot]=0;
            if(u>0)r[tot]=min(r[tot],(double)(xr-x)/u);
            if(u<0)r[tot]=min(r[tot],(double)(xl-x)/u);
            if(v>0)r[tot]=min(r[tot],(double)(yr-y)/v);
            if(v<0)r[tot]=min(r[tot],(double)(yl-y)/v);
        }
        else{
            if(u>0){//向右飞 
                l[tot]=max(l[tot],(double)(xl-x)/u);//飞到左边界 
                r[tot]=min(r[tot],(double)(xr-x)/u);//飞到右边界 
            }
            if(u<0){//向左飞 
                l[tot]=max(l[tot],(double)(xr-x)/u);//飞到右边界
                r[tot]=min(r[tot],(double)(xl-x)/u);//飞到左边界
            }
            
            if(v>0){//向上飞 
                l[tot]=max(l[tot],(double)(yl-y)/v);
                r[tot]=min(r[tot],(double)(yr-y)/v);
            }
            if(v<0){//向下飞 
                l[tot]=max(l[tot],(double)(yr-y)/v);
                r[tot]=min(r[tot],(double)(yl-y)/v);
            }
        }
    }
    //for(int i=1;i<=n;i++)printf("%.2lf %.2lf\n",l[i],r[i]);
    for(int i=1;i<=tot;i++){
        h1[++cnt1]=l[i];
        h1[++cnt1]=r[i];
    }
    sort(h1+1,h1+cnt1+1);
    h[++cnt]=h1[1];
    for(int i=2;i<=cnt1;i++)
        if(h1[i]!=h1[i-1])h[++cnt]=h1[i];
    for(int i=1;i<=tot;i++){
        int pos=find(l[i]);
        sum[pos]++;
        pos=find(r[i]);
        sum[pos+1]--;
    }
    int mx=0,id=0;
    for(int i=1;i<=n;i++){
        sum[i]+=sum[i-1];
        if(sum[i]>mx)mx=sum[i],id=i;
    }
    printf("%.0lf",h[id]);
}
30分 算出所有弹幕出现的时间段+离散化+差分

 

#include<cstdio>
#include<algorithm>
using namespace std;
int INF=0x7fffffff;
int in[100010]={0},out[100010]={0};
int a[100010]={0};
int main(){
    freopen("camera.in","r",stdin);
    freopen("camera.out","w",stdout);
    int i,n,xl,yl,xr,yr,cnt=1,sum=0,maxc=0,ans;
    scanf("%d%d%d%d%d",&n,&xl,&yl,&xr,&yr);
    for(i=0;i<n;i++){
        int x,y,u,v;
        int txs=-1,txe=INF,tys=-1,tye=INF,ts=-1,te=-1;
        scanf("%d%d%d%d",&x,&y,&u,&v);
        if((x<xl&&u<=0)||(x>xr&&u>=0))continue;
        if((y<yl&&v<=0)||(y>yr&&v>=0))continue;
        if(x>=xl&&x<=xr&&y>=yl&&y<=yr){
            ts=0;
            if(u==0&&v==0)te=INF;
            else if(u==0){
                if(v>0)te=(yr-y)/v;
                else{v=-v;te=(y-yl)/v;}
            }
            else if(v==0){
                if(u>0)te=(xr-x)/u;
                else{u=-u;te=(x-xl)/u;}
            }
            else{
                if(u>0)txe=(xr-x)/u;
                else{u=-u;txe=(x-xl)/u;}
                if(v>0)txe=(yr-y)/v;
                else{v=-v;tye=(y-yl)/v;}
                te=min(txe,tye);
            }
        }
        else{
            if(u<0)u=-u;
            if(v<0)v=-v;
            if(u==0){
                if(y
                <=yl){tys=(yl-y+v-1)/v;tye=(yr-y)/v;}
                if(y>=yr){tys=(y-yr+v-1)/v;tye=(y-yl)/v;}
            }
            else if(v==0){
                if(x<=xl){txs=(xl-x+u-1)/u;txe=(xr-x)/u;}
                if(x>=xr){txs=(x-xr+u-1)/u;txe=(x-xl)/u;}
            }
            else{
                if(x<=xl){txs=(xl-x+u-1)/u;txe=(xr-x)/u;}
                if(x>=xr){txs=(x-xr+u-1)/u;txe=(x-xl)/u;}
                if(y<=yl){tys=(yl-y+v-1)/v;tye=(yr-y)/v;}
                if(y>=yr){tys=(y-yr+v-1)/v;tye=(y-yl)/v;}
            }
            ts=max(txs,tys);
            te=min(txe,tye);
        }
        in[cnt]=ts;out[cnt++]=te;
    }
    for(i=1;i<=cnt-1;i++){a[in[i]]++;a[out[i]+1]--;}
    for(i=1;i<=cnt-1;i++){sum+=a[i];if(sum>maxc){maxc=sum;ans=i;}}
    printf("%d",ans);
    return 0;
}