PA的第一题,过是很好过,一开始用暴力循环,55分。
后来开始想用sort和二分查找来降低复杂度,可是清华的OJ不支持algorithm,之后在别人的博客上看到了qsqrt的方法,之后接见了别人的代码,终于100过了。。不过发现好多问题。
1.给定输入n的数目是50000.直接int S[50000]会超时,但是先define L 50000;在int S[L]就不会....
2.scanf比cin快好多,之前做poj也发现了,最好是使用scanf和printf
3.之后是一个二分查找问题,一开始以为挺简单,但是在实际应用这个题的时候还需要一些修改。(二分查找貌似在这门课还没讲,现在就用到是不是赖皮了。。)
4先贴代码吧
#include<stdio.h>
#include<stdlib.h>
#define L 500005
int S[L];
int compare(const void *a, const void *b)
{
int *pa = (int*)a;
int *pb = (int*)b;
return (*pa )- (*pb); //关于qsort函数的运用,参考http://www.cnblogs.com/CCBB/archive/2010/01/15/1648827.html
}
//
void swap(int &a,int &b)
{
int tmp = a;
a = b;
b = tmp;
}//交换函数用来保证输入的有序性,一开始并没有想到,唉。
int ssort(int min, int max, int des)
{
int mid ,left = min, right = max;
while(left <= right)
{
mid = left + ((right - left) >> 1);//这里也是需要注意的地方,mid不仅仅是(left+right)/2,一方面防止溢出
//另一方面,采用移位比除以二要更快
if (S[mid] >= des)
right = mid - 1;
else
left = mid + 1;
}
return left;
}//这个二分查找是关键所在,
//在这次所应用的二分查找中,不能保证查找的数在数组中存在,考虑一个闭区间[a,b],假设我查找A,这个a,在数组中不存在,由于二分查找相当于向中逼近,因此总会存在一个时刻使得S[i] < a < S[i+1],这里上述代码的处理就比巧妙了,返回的是left而不是middle,因为最后一次的left是比middle大1的,而我们在求得的序号是第一个开区间内最小的数字。
int main()
{
int n ,m;
scanf("%d %d\n",&n ,&m);
int a,b;
for(int i = 0; i < n; i++ )
{
scanf("%d",&S[i]);
}
qsort(S, n, sizeof(int), compare);//这里是qsqrt的运用
for(int i =0;i < m;i++)
{
scanf("%d %d",&a ,&b);
if(a > b)
swap(a,b); //保证a<b
int le = ssort(0, n - 1, a);
int ri = ssort(0, n - 1, b);
int ans = ri - le;
if (S[ri] == b) //这里处理的也是和之前的二分法相吻合,考虑到区间上限不一定存在于数组的问 //题若最终查找的中间值是开始的上界,说明数组中的最大数也是在区间之内的,
//因此,需要加一个数
ans ++;
if (ans < 0)
ans = 0; //为了应付可能出现的负数
printf("%d\n",ans);
}
return 0;
}
总结,这个题的关键还是那个二分法以及后续的处理,我通过一个下午的反复琢磨已经背过了。