3 2 5 2 3 6 2
0 2HintIn this test case, there are 3 trees whose heights are 5 2 3. For the query 6, if CodeFamer cuts the tree whose height is not large than 6, the height form of left trees are -1 -1 -1(-1 means this tree was cut). Thus there is 0 block. For the query 2, if CodeFamer cuts the tree whose height is not large than 2, the height form of left trees are 5 -1 3(-1 means this tree was cut). Thus there are 2 blocks.
STL中关于二分查找的函数有三个lower_bound 、upper_bound 、binary_search 。这三个函数都运用于有序区间(当然这也是运用二分查找的前提),下面记录一下这两个函数。
ForwardIter lower_bound(ForwardIter first, ForwardIter last,const _Tp& val)算法返回一个非递减序列[first, last)中的第一个大于等于值val的位置。
ForwardIter upper_bound(ForwardIter first, ForwardIter last, const _Tp& val)算法返回一个非递减序列[first, last)中的第一个大于值val的位置。
AC代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int maxn = 100005; int n, q; int h[maxn], ans[maxn], vis[maxn]; pair<int, int> p[maxn]; int main() { while(scanf("%d %d", &n, &q) != EOF) { for(int i = 1; i <= n; i++) { scanf("%d", h + i); p[i] = make_pair(-h[i], i); } memset(vis, 0, sizeof(vis)); sort(p + 1, p + n + 1);//因为存的是负值,所以是从大到小排序 int sum = 0;//记录当前有多少个块 for(int i = 1; i <= n; i++) { int x = p[i].second; if(!vis[x - 1] && !vis[x + 1]) sum ++;//多一个块,因为两边都没被访问 else if(vis[x - 1] && vis[x + 1]) sum --;//合并两个块为一个,因为正好将两边连了起来,其他情况不会影响块的增加与减少 ans[i] = sum;//这里表示从第i个数据以下(数据是从大到小的)射击能够得到的块数 vis[x] = 1; } for(int i = 0; i < q; i++) { int t; scanf("%d", &t);//upper_bound返回一个非递减序列[first, last)中的第一个大于值val的位置。 int id = upper_bound(p + 1, p + n + 1, make_pair(-t, -1)) - p - 1; printf("%d\n", ans[id]); } } return 0; }