zoukankan      html  css  js  c++  java
  • [线段树][数学][离散化]luogu P2928 牛的打手

    https://www.luogu.org/problemnew/show/P2928

    分析

    一道挺有意思的思维题

    因为所有点都在运动,不好做,我们把运动改为相对的

    设bessie在原点(0,0),不运动,则杀手们的参数则为(x-bx,y-by,vx-vbx,vy-vby)

    那么题目就变为求杀手什么时候进入或相切以r为半径原点为圆心的圆

    可以有方程:

    $r^2=(x+tvx)^2+(y+tvy)^2$

    化为常规式

    $(vx^2+vy^2)t^2+2*(xcdot vx+ycdot vy)t+x^2+y^2-r^2=0$

    然后解出方程,将两个解存进数组里,排序离散化

    拿个线段树来累计答案即可

    注意:

    1、如果有在相对运动中不运动的点,要判断是否一直在圆内或上
    2、要判无解,解小于0等情况

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef double db;
    const int N=5e4+10;
    struct Cow {
        db x,y,vx,vy;
        void In() {scanf("%lf%lf%lf%lf",&x,&y,&vx,&vy);}
        Cow operator - (Cow &b) {
            return (Cow){x-b.x,y-b.y,vx-b.vx,vy-b.vy};
        }
    }t,a[N];
    int s[N<<3],lz[N<<3],rt=1;
    int cnt;
    db p[2*N],q[N][2];
    int n,r,ans,e;
    
    void Calc(int x) {
        db A=pow(a[x].vx,2)+pow(a[x].vy,2),B=2*a[x].x*a[x].vx+2*a[x].y*a[x].vy,
        C=pow(a[x].x,2)+pow(a[x].y,2)-pow(r,2);
        db delta=pow(B,2)-4.0*A*C;
        if (delta<0.0) return;
        db d_root=sqrt(delta);
        db x1=(-1.0*B-d_root)/(2.0*A),x2=(-1.0*B+d_root)/(2.0*A);
        if (x1<0.0) x1=0;if (x2<=0.0) return;
        p[++cnt]=x1,1;p[++cnt]=x2,-1;
        q[cnt>>1][0]=x1;q[cnt>>1][1]=x2;
    }
    
    void Pushdown(int x) {
        s[x<<1]+=lz[x];lz[x<<1]+=lz[x];
        s[(x<<1)+1]+=lz[x];lz[(x<<1)+1]+=lz[x];
        lz[x]=0;
    }
    
    void Add(int x,int l,int r,int L,int R) {
        if (r<L||R<l||r<l) return;
        if (L<=l&&r<=R) {
            s[x]++;lz[x]++;
            return;
        }
        Pushdown(x);
        int mid=l+r>>1;
        if (L<=mid) Add(x<<1,l,mid,L,R);
        if (mid<R) Add((x<<1)+1,mid+1,r,L,R);
        s[x]=max(s[x<<1],s[(x<<1)+1]);
    }
    
    int main() {
        scanf("%d%d",&n,&r);
        t.In();
        for (int i=1;i<=n;i++) a[i].In(),a[i]=a[i]-t;
        for (int i=1;i<=n;i++)
            if (a[i].vx!=0||a[i].vy!=0) Calc(i);
                else if (pow(a[i].x,2)+pow(a[i].y,2)<=pow(r,2)) e++;
        sort(p+1,p+cnt+1);
        for (int i=1;i<=(cnt>>1);i++) {
            int l=lower_bound(p+1,p+cnt+1,q[i][0])-p,r=lower_bound(p+1,p+cnt+1,q[i][1])-p;
            Add(rt,1,cnt,l,r);
        }
        ans=s[rt]+e;
        printf("%d",ans);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    android 选择图片或拍照时旋转了90度问题
    拍照选择图片(Activity底部弹出)
    Dialog 自定义使用1
    Dialog 基本使用
    秒杀主流应用的二维码扫描
    gen already exists but is not a source folder. Convert to a source folder or rename it.
    gen already exists but is not a source folder. Convert to a source folder or rename it.
    Unable to execute dex: Multiple dex files define
    xxxx is not translated in zh-rCN, zh-rTW
    Android Application 对象介绍
  • 原文地址:https://www.cnblogs.com/mastervan/p/11123382.html
Copyright © 2011-2022 走看看