zoukankan      html  css  js  c++  java
  • FJUT ACM 2367题 二分强化——浮点数序列查询

    Problem Description

    已知在二维空间中有n个点,p0,p1……pn-1

    已按照x为第一优先级,y为第二优先级从大到小排好序;

    即若 pi<pj

    则pi.x<pj.x,或者pi.x==pj.x&&pi.y<pj.y

    Input

    只有一组数据
    第一行是两个整数n,m分别代表点的个数和查询次数
    接下来n行,每行有二个带三位小数的浮点数x,y代表一个点的坐标
    再接下来m行,每行的有4个数字x1,y1,x2,y2代表p1,p2且p1>=p2

    其中n,m<=100000;

    任意0<=x,y<10^6;

    Output

    输出n个点所有小于等于p1且大于等于p2的点的下标之和

    SampleInput
    6 4
    125.689 125.689
    125.689 125.688
    125.688 125.689
    125.688 125.689
    125.688 125.688
    125.688 125.688
    125.688 125.688 125.688 125.688
    125.688 125.689 125.688 125.688
    125.689 125.689 125.688 125.689
    125.688 125.689 125.688 125.689
    
    SampleOutput
    9
    14
    6
    5

    该题很明显就是一个二分的题目,(ps:题目告诉你就是二分强化啊。。。)
    该题要求的事寻找一个小于等于p1且大于等于p2的点的下标之和,就是说是寻找一个范围,在将范围的值累加起来,而在寻找的过程中采取遍历的话,其结果是必定超时的!
    所以我们应该用二分去寻找两个下标,一个去寻找小于等于p1的下标,一个去寻找比p2大的下标,这时候我们很有可能写个for循环将p1与p2的值累加起来,但是这种操作会导致
    凉凉(TLE),我们这个时候可以使用求和公式,因为从p1到p2必定是一个等差数列,且d=1;用等差数列求和公式求解就可以了!
    而寻找的过程,是一个二维二分的过程,(其实还有一种黑科技,来至CWL学长,他说乘于一个数值,使其可以用一维来表示,然后就是一维的二分了)
    其实二维二分并不难,在x相等的情况下讨论y就可以了
    1.x相等的情况下,y大于或等于
    2.x相等的情况下,y小于
    3.x大于或等于
    4.x小于
    备注:给的数据是从大到小排列,因为一开始我的思路是从小到大,为了偷懒,我把读取倒过来了,所以算结果那块会有点乱
    #include<stdio.h>
    #include<string.h>
    ///结构体,二维的二分,暴力不能过,emmmmmm
    typedef struct Mydouble
    {
        double x;
        double y;
    } mydouble;
    long long Tmaxfind(double a,double b,int n, mydouble x[])
    {
        int left,right,mid;
        left=-1;
        right=n;
        mid=(left+right)/2;
        while(left+1<right)
        {
            if(x[mid].x>a||(x[mid].x==a&&x[mid].y>b))
            {
                right=mid;
                mid=(right+left)/2;
                continue;
            }
            if(x[mid].x<a||(x[mid].x==a&&x[mid].y<=b))
            {
                left=mid;
                mid=(left+right)/2;
                continue;
            }
        }
        return right;///还回的是大一号的值的下标
    }
    long long Tminfind(double a,double b,int n, mydouble x[])
    {
        int left,right,mid;
        left=-1;
        right=n;
        mid=(left+right)/2;
        while(left+1<right)
        {
            if(x[mid].x>a||(x[mid].x==a&&x[mid].y>=b))
            {
                right=mid;
                mid=(right+left)/2;
                continue;
            }
            if(x[mid].x<a||(x[mid].x==a&&x[mid].y<b))
            {
                left=mid;
                mid=(left+right)/2;
                continue;
            }
        }
        return right;///还回的是这个值的最小小标
    }
    mydouble x[100005];
    int main()
    {
        int n,m,i,j;
        mydouble a,b;
        long long c,d,e;long long sum;
        while(~scanf("%d%d",&n,&m))
        {
            for(i=n-1; i!=-1; i--)
            {
                scanf("%lf%lf",&x[i].x,&x[i].y);
            }
            for(i=0; i<m; i++)
            {
                scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
                sum=0;
                d=Tmaxfind(a.x,a.y,n,x);
                e=Tminfind(b.x,b.y,n,x);
                //printf("大的值+1的下标=%d 小的值最小下标%d
    ",d,e);
                sum=(((n-d-1)+(n-e))*(d-e))/2;
                /*for(e;e<d;e++)
                {
                    sum+=(n-1-e);
                }*/
                printf("%lld
    ",sum);
            }
        }
    }
     
  • 相关阅读:
    【最短路】BAPC2014 B Button Bashing (Codeforces GYM 100526)
    【链表】【模拟】Codeforces 706E Working routine
    【数论】【扩展欧几里得】Codeforces 710D Two Arithmetic Progressions
    【动态规划】【最短路】Codeforces 710E Generate a String
    【模拟】Codeforces 710C Magic Odd Square
    【模拟】Codeforces 710B Optimal Point on a Line
    【模拟】Codeforces 710A King Moves
    【模拟】Codeforces 705A Hulk
    【模拟】Codeforces 705B Spider Man
    【模拟】Codeforces 704A & 705C Thor
  • 原文地址:https://www.cnblogs.com/qq136155330/p/8135189.html
Copyright © 2011-2022 走看看