FJUT寒假第一周作业浮点数查寻题解
二分强化——浮点数序列查询
TimeLimit:4000MS MemoryLimit:128MB
64-bit integer IO format:%I64d
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
明显是二分,没啥好解释的。
输出:n个点所有小于等于p1且大于等于p2的点的下标之和因为是包括等于,
所以我们可以用二分直接找出和点(x1,y1)相等的最小下标(数是从大到小,所以是最小下标)并记录,
接着在从(i-1)~n中找出和点(x2,y2)相等的最大下标
最小下标和,很容易看出是一个等差数列求和
这题唯一的坑:本身数据是不超过int,但是下标和为爆int 所以要用long long
下面附上部分核心代码:
x=-1;//x为下界 s=n;//s为上界 scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); while(x+1<s) { z=(s+x)/2;//中 if(a[z]>x1||(a[z]==x1&&b[z]>y1))//第一优先级大于或者第一相等 第二大于 x=z; else s=z; } i=s;//i用来存点(x1,y1)相等的最小下标 x=s-1;//缩小下界范围减时间,因为x1y1 大于x2y2,所以下界最小为s-1 s=n;//上界不变 while(x+1<s) { z=(s+x)/2; if(a[z]>e||(a[z]==x2&&b[z]>=y2)) x=z; else s=z; } s=s-1;//上面二分求出的是小于(x2,y2)的最小下标,减1后就是相等的最大下标 printf("%lld\n",(i+s)*(s-i+1)/2);//s-i+1是i~s的长度