现有N个大理石,每个大理石上写了一个非负整数。首先把各数从小到大排序,然后回 答Q个问题。每个问题问是否有一个大理石写着某个整数x,如果是,还要回答哪个大理石上 写着x。排序后的大理石从左到右编号为1~N。(在样例中,为了节约篇幅,所有大理石上 的数合并到一行,所有问题也合并到一行。)
样例输入:
4 1 (N Q)
2 3 5 1 (石头)
5 (问题)
5 2
1 3 3 3 1
2 3
样例输出:
CASE #1:
5 found at 4
CASE #2:
2 not found
3 found at 3
#include<iostream> #include<stdio.h> #include<string> #include<algorithm> using namespace std; int main() { int N, Q; while (scanf("%d%d", &N, &Q) == 2) { int *a = new int[N]; int *b = new int[Q]; for(int i=0;i<N;i++) scanf("%d", &a[i]); for(int j=0;j<Q;j++) scanf("%d", &b[j]); sort(a, a + N); bool flag=false; for (int k = 0; k < Q; k++) { for (int l = 0; l < N; l++) if (b[k] == a[l]) { flag = true; printf("%d found at %d\n", b[k], l + 1); break; } if (flag != true) { printf("%d not found\n", b[k]); } } delete[]a; delete[]b; a = NULL; b = NULL; } }
很基础的排序和查找,然而自己却卡在while上一会,不心细果然什么都办不了
用stl会快很多
#include<cstdio> #include<algorithm> using namespace std; const int maxn = 10000; int main() { int n, q, x, a[maxn], kase = 0; while (scanf("%d%d", &n, &q) == 2 && n) { printf("CASE# %d:\n", ++kase); for (int i = 0; i < n; i++) scanf("%d", &a[i]); sort(a, a + n); //排序 while(q--) { scanf("%d", &x); int p = lower_bound(a, a+n, x) - a; //在已排序数组a中寻找x if(a[p] == x) printf("%d found at %d\n", x, p+1); else printf("%d not found\n", x); } } return 0; }
sort
排序,并非只是普通的快速排序,除了对普通的快速排序进行优化,它还结合了插入排序和堆排序。根据不同的数量级别以及不同情况,能自动选用合适的排序方法。当数据量较大时采用快速排序,分段递归。一旦分段后的数据量小于某个阀值,为避免递归调用带来过大的额外负荷,便会改用插入排序。而如果递归层次过深,有出现最坏情况的倾向,还会改用堆排序。
#include <algorithm> template< class RandomIt > void sort( RandomIt first, RandomIt last ); template< class RandomIt, class Compare > void sort( RandomIt first, RandomIt last, Compare comp );
cmp的用法自行定义
例如:
#include<iostream> #include<stdio.h> #include<string> #include<algorithm> using namespace std; struct Node { int x, y; }p[1001]; int n; int cmp(Node a, Node b) { if (a.x != b.x) return a.x < b.x; //如果a.x不等于b.x,就按x从小到大排 return a.y < b.y; //如果x相等按y从小到大排 } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d%d", &p[i].x, &p[i].y); sort(p + 1, p + n + 1, cmp); for (int i = 1; i <= n; i++) printf("%d %d\n", p[i].x, p[i].y); return 0; }
lower_bound
查找一个比自己大或者和自己相等的数并返回它的位置
注意:调用lower_bound之前必须确定序列为有序序列,否则调用出错。
template<class ForwardIterator, class Type> ForwardIterator lower_bound( ForwardIterator _First, ForwardIterator _Last, const Type& _Val ); template<class ForwardIterator, class Type, class BinaryPredicate> ForwardIterator lower_bound( ForwardIterator _First, ForwardIterator _Last, const Type& _Val, BinaryPredicate _Comp );
传入参数说明:
_First 要查找区间的起始位置
_Last 要查找区间的结束位置
_Val 给定用来查找的值
_Comp 自定义的表示小于关系的函数对象,根据某个元素是否满足小于关系而返回true或者false
lower_bound(first,last,val)表示找到第一个>=val的值的地址
upper_bound(first,last,val)表示找到第一个>val的值的地址
在lower_bound(first,last,val,cmp)中cmp是比较函数
在lower_bound(first,last,val)中cmp默认为
bool cmp(mid,val){ return mid<val;//表示如果mid<val 则继续lower_bound }
所以当mid>=val时停止