THU数据结构编程作业一:查询范围(Range)
2015-09-24 21:00
453 查看
查询范围(Range)
描述
数轴上有n个点,对于任一闭区间 [a, b],试计算落在其内的点数。
输入
第一行包括两个整数:点的总数n,查询的次数m。
第二行包含n个数,为各个点的坐标。
以下m行,各包含两个整数:查询区间的左、右边界a和b。
输出
对每次查询,输出落在闭区间[a, b]内点的个数。
样例
Input
Output
限制
0 ≤ n, m ≤ 5×10^5
对于次查询的区间[a, b],都有a ≤ b
各点的坐标互异
各点的坐标、查询区间的边界a、b,均为不超过10^7的非负整数
时间:2 sec
内存:256 MB
先上完整程序:
以上程序能够100%通过THU的OJ。
本题设计的主要思路是:
···首先对数轴上的点进行排序(开始以为给定的输出点已经排好序,后来发现并不是);
···确定给定的区间端点在点序列中的位置应该在哪里,注意区间是闭合的,端点问题需要着重考虑的;
···确定两端点的位置之后就可以计算出该区间包含有多少个点了。
注意:题目中的坐标和查询范围大于等于0并且均不超过10^7,因此我在坐标数组的开头和结尾分别插入一个哨兵(sentry)。见程序的30行和31行,方便确定查询边界点在坐标数组中的位置,也因此数组的大小增加了2.
一下部分程序的解释:
1、 OJ上测试的数据量是非常大的,所以在设计程序时必须考虑时间复杂度。首先为了实现快速输入输出,调大流缓冲区。
开始我没有想到要把流缓冲区调大,所以程序运行的速度比较慢,在做到第二题的时候看到大神的代码才恍然大悟:/article/11199971.html
2、 输入输出重定向
为了方便调试,将输入输出(printf,scanf)进行了重定向,直接从文件读取并输出到文件。c++中hi、还有另外一种方法对cin,cout重定向:
主函数结束之前重置输入输出:
3、本体的重点应该在排序和查找算法上,因为数据量很大,因此我选择了二分查找(时间复杂度log(n))和快速排序算法
(最理想的时间复杂度为nlog(n),有看到过说随机快速排序更好点)
二分查找:因为要考虑边界问题所以我加入了一个记录边界是否包含的函数参数(int & border)。
快速排序有两种写法:
另外,THU的OJ中去掉了例如vector,algorithm的头文件,所以写C++的时候会有点纠结到底哪些头文件可以用哪些不可以用,所以尽量只适用基本的数据类型和操作。
描述
数轴上有n个点,对于任一闭区间 [a, b],试计算落在其内的点数。
输入
第一行包括两个整数:点的总数n,查询的次数m。
第二行包含n个数,为各个点的坐标。
以下m行,各包含两个整数:查询区间的左、右边界a和b。
输出
对每次查询,输出落在闭区间[a, b]内点的个数。
样例
Input
5 2 1 3 7 9 11 4 6 7 12
Output
0 3
限制
0 ≤ n, m ≤ 5×10^5
对于次查询的区间[a, b],都有a ≤ b
各点的坐标互异
各点的坐标、查询区间的边界a、b,均为不超过10^7的非负整数
时间:2 sec
内存:256 MB
先上完整程序:
#include<iostream> #include<cstdio> using namespace std; const int SZ = 1<<20; struct fastio{ //fast io char inbuf[SZ]; char outbuf[SZ]; fastio(){ setvbuf(stdin,inbuf,_IOFBF,SZ); setvbuf(stdout,outbuf,_IOFBF,SZ); } }io; int binary_search(int *a, int Length, int goal, int &border); void QuickSort(int *a, int lo, int hi); int main(){ #ifndef _OJ_ freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); #endif int IntervalSize(0), QueryTimes(0); // interval size and query times int *points; //store interval points scanf("%d %d", &IntervalSize, &QueryTimes); points = new int[IntervalSize + 2](); //new memory for interval points for(int i = 1; i < IntervalSize + 1; ++i) scanf("%d", &points[i]); points[0] = -1; //set a sentry points[IntervalSize + 1] = 10000000+1; //set a sentry QuickSort(points, 0, IntervalSize + 1); int (*query)[2] = new int[QueryTimes][2](); //new memory for query interval for(int i = 0; i < QueryTimes; ++i) scanf("%d %d", &query[i][0], &query[i][1]); int *result = new int[QueryTimes](); //new memory to store results for(int i = 0; i < QueryTimes; ++i){ //find the subscripts of query intervals and get the subtrations as the resluts int borderL(0), borderR(0), diff; diff = binary_search(points, IntervalSize+2, query[i][1], borderR) - binary_search(points, IntervalSize+2, query[i][0], borderL); if(borderL && borderR) result[i] = diff + 1; else if(borderL && !borderR) result[i] = diff + 1; else result[i] = diff; } for(int i = 0; i < QueryTimes; ++i) printf("%d\n", result[i]); delete[] points; delete[] query; delete[] result; return 0; } int binary_search(int *a, int Length, int goal, int &border){ int lo = 0, hi = Length - 1; while (lo <= hi){ int mid = (lo + hi) / 2; if(a[mid] <= goal && goal < a[mid + 1]){ if(a[mid] == goal){ border = 1; return mid ; }else return mid; }else if(a[mid] > goal) hi = mid ; else lo = mid ; } } //quick sort 1 void QuickSort(int *a, int lo, int hi){ if(lo < hi){ int i = lo, j = hi, x = a[lo]; while(i < j){ while(i < j && a[j] >= x) --j; if(i < j) a[i++] = a[j]; while(i < j && a[i] < x) ++i; if(i < j) a[j--] = a[i]; } a[i] = x; QuickSort(a, lo, i-1); QuickSort(a, i+1, hi); } } //quick sort 2 /* inline void Swap( int &i, int &j){ int k; k = i; i = j; j = k; } int quick_sort(int *a, int lo, int hi){ int index = lo, x = a[lo]; Swap(a[lo], a[hi]); for(int i = lo; i < hi; ++i){ if(a[i] < x) Swap(a[index++], a[i]); } Swap(a[index], a[hi]); return index; } void QuickSort(int *a, int lo, int hi){ if(lo < hi){ int index = quick_sort(a, lo, hi); QuickSort(a, lo, index-1); QuickSort(a, index+1, hi); } } */
以上程序能够100%通过THU的OJ。
本题设计的主要思路是:
···首先对数轴上的点进行排序(开始以为给定的输出点已经排好序,后来发现并不是);
···确定给定的区间端点在点序列中的位置应该在哪里,注意区间是闭合的,端点问题需要着重考虑的;
···确定两端点的位置之后就可以计算出该区间包含有多少个点了。
注意:题目中的坐标和查询范围大于等于0并且均不超过10^7,因此我在坐标数组的开头和结尾分别插入一个哨兵(sentry)。见程序的30行和31行,方便确定查询边界点在坐标数组中的位置,也因此数组的大小增加了2.
一下部分程序的解释:
1、 OJ上测试的数据量是非常大的,所以在设计程序时必须考虑时间复杂度。首先为了实现快速输入输出,调大流缓冲区。
const int SZ = 1<<20; struct fastio{ //fast io char inbuf[SZ]; char outbuf[SZ]; fastio(){ setvbuf(stdin,inbuf,_IOFBF,SZ); setvbuf(stdout,outbuf,_IOFBF,SZ); } }io;
开始我没有想到要把流缓冲区调大,所以程序运行的速度比较慢,在做到第二题的时候看到大神的代码才恍然大悟:/article/11199971.html
2、 输入输出重定向
#ifndef _OJ_ freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); #endif
为了方便调试,将输入输出(printf,scanf)进行了重定向,直接从文件读取并输出到文件。c++中hi、还有另外一种方法对cin,cout重定向:
std::ifstream in("in.txt"); std::streambuf *cinbuf = std::cin.rdbuf(); //save old buff std::cin.rdbuf(in.rdbuf()); //redirect std::cin to in.txt! std::ofstream out("out.txt"); std::streambuf *coutbuf = std::cout.rdbuf(); //save old buf std::cout.rdbuf(out.rdbuf()); //redirect std::cout to out.txt!
主函数结束之前重置输入输出:
std::cin.rdbuf(cinbuf); //reset to standard input again std::cout.rdbuf(coutbuf); //reset to standard output again
3、本体的重点应该在排序和查找算法上,因为数据量很大,因此我选择了二分查找(时间复杂度log(n))和快速排序算法
(最理想的时间复杂度为nlog(n),有看到过说随机快速排序更好点)
二分查找:因为要考虑边界问题所以我加入了一个记录边界是否包含的函数参数(int & border)。
int binary_search(int *a, int Length, int goal, int &border){ int lo = 0, hi = Length - 1; while (lo <= hi){ int mid = (lo + hi) / 2; if(a[mid] <= goal && goal < a[mid + 1]){ if(a[mid] == goal){ border = 1; return mid ; }else return mid; }else if(a[mid] > goal) hi = mid ; else lo = mid ; } }
快速排序有两种写法:
//quick sort 1 void QuickSort(int *a, int lo, int hi){ if(lo < hi){ int i = lo, j = hi, x = a[lo]; while(i < j){ while(i < j && a[j] >= x) --j; if(i < j) a[i++] = a[j]; while(i < j && a[i] < x) ++i; if(i < j) a[j--] = a[i]; } a[i] = x; QuickSort(a, lo, i-1); QuickSort(a, i+1, hi); } }
/* inline void Swap( int &i, int &j){ int k; k = i; i = j; j = k; } int quick_sort(int *a, int lo, int hi){ int index = lo, x = a[lo]; Swap(a[lo], a[hi]); for(int i = lo; i < hi; ++i){ if(a[i] < x) Swap(a[index++], a[i]); } Swap(a[index], a[hi]); return index; } void QuickSort(int *a, int lo, int hi){ if(lo < hi){ int index = quick_sort(a, lo, hi); QuickSort(a, lo, index-1); QuickSort(a, index+1, hi); } }
另外,THU的OJ中去掉了例如vector,algorithm的头文件,所以写C++的时候会有点纠结到底哪些头文件可以用哪些不可以用,所以尽量只适用基本的数据类型和操作。
相关文章推荐
- C语言中结构体与指针的若干问题(在数据结构中的应用)
- 数据结构 —— 第一个程序 【顺序表】
- 数据结构分析之线性哈希表(Linear Hash Tables)
- OpenCV CvMat数据结构参数
- 一步一步写平衡二叉树(AVL树)
- 基本数据结构:二叉树(binary tree)
- 基本数据结构:树(tree)
- 《大话数据结构》之静态链表
- 《大话数据结构》之单链表
- 数据结构之链表定义及基本操作实现
- 【软考】-数据结构-平衡二叉树
- 数据结构与算法分析(c++版) #11 链式队列
- SkipList数据结构学习
- 数据结构和算法导论
- 数据结构与算法分析(c++版) #10 顺序队列
- 数据结构与算法分析(c++版) #9 队列
- java 数据结构
- [是用数据结构]UVa1471 - Defense Lines
- Java数据结构与算法
- C语言数据结构之单链表的拆分