洛谷 P3184 [USACO16DEC]Counting Haybales数草垛
题目描述
Farmer John has just arranged his NN haybales (1 leq N leq 100,0001≤N≤100,000 ) at various points along the one-dimensional road running across his farm. To make sure they are spaced out appropriately, please help him answer QQ queries (1 leq Q leq 100,0001≤Q≤100,000 ), each asking for the number of haybales within a specific interval along the road.
农夫John在一条穿过他的农场的路上(直线)放了N个干草垛(1<=N<=100,000),每个干草垛都在不同的点上。为了让每个干草垛之间都隔着一定的距离,请你回答农夫John的Q个问题(1<=Q<=100,000),每个问题都会给出一个范围,询问在这个范围内有多少个干草垛。
(其实就是有一条数轴上有N个不重复的点,再问Q个问题,每个问题是给出一个范围,问此范围内有多少个点?)
(在给出范围的边界上也算)
输入输出格式
输入格式:
The first line contains NN and QQ .
The next line contains NN distinct integers, each in the range 0 ldots 1,000,000,0000…1,000,000,000 , indicating that there is a haybale at each of those locations.
Each of the next QQ lines contains two integers AA and BB (0 leq A leq B leq 1,000,000,0000≤A≤B≤1,000,000,000 ) giving a query for the number of haybales between AA and BB , inclusive.
第一行包括N和Q
第二行有N个数字,每个数字的范围在0~1,000,000,000,表示此位置有一个干草垛。
接下来的Q行,每行包括两个数字,A和B(0<=A<=B<=1,000,000,000)表示每个询问的范围
输出格式:
You should write QQ lines of output. For each query, output the number of haybales in its respective interval.
总共Q行,每行输出此范围内的干草垛数量
输入输出样例
思路:区间求和 难度:普及/提高-
暴力:线段树。只能过一个点,因为测试数据太大(109),而线段树最多能开到107
#include<cstdio> #define N 10000005 using namespace std; int n, m, x, y; struct nond { int ll, rr; int sum; }tree[4*N]; void up(int now) { tree[now].sum = tree[now*2].sum+tree[now*2+1].sum; } void build(int now, int l, int r) { tree[now].ll = l; tree[now].rr = r; if(l == r) { tree[now].sum = 0; return ; } int mid = (l+r) / 2; build(now*2, l, mid); build(now*2+1, mid+1, r); up(now); } void change(int now, int s) { if(tree[now].ll == tree[now].rr) { tree[now].sum ++; return ; } int mid = (tree[now].ll+tree[now].rr) / 2; if(s<=mid) change(now*2, s); else change(now*2+1, s); up(now); } int query(int now, int l, int r) { if(tree[now].ll==l && tree[now].rr==r) { return tree[now].sum; } int mid = (tree[now].ll+tree[now].rr) / 2; if(l<=mid && mid<r) return query(now*2, l, mid) + query(now*2+1, mid+1, r); else if(r<=mid) return query(now*2, l, r); else return query(now*2+1, l, r); } int main() { int a[100005] = {0}, maxn = -1; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); if(a[i] > maxn) maxn = a[i]; } build(1, 1, maxn); for(int i = 1; i <= n; i++) change(1, a[i]); for(int i = 1; i <= m; i++) { scanf("%d%d", &x, &y); if(x > maxn) { printf("0 "); continue; } printf("%d ", query(1, x, y)); } return 0; }
正解:运用 c++中的 lower_bound、upper_bound
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 100010 using namespace std; int n, m, q, tot; int pos[MAXN], hash[MAXN]; int main() { scanf("%d%d", &n, &q); for(int i = 1; i <= n; i++) scanf("%d", &pos[i]); sort(pos+1, pos+1+n); for(int i = 1; i <= q; i++) { int x, y; scanf("%d%d", &x, &y); cout << upper_bound(pos+1, pos+n+1, y) - lower_bound(pos+1, pos+n+1, x) << ‘ ’; } return 0; }
PS:lower_bound(val) :返回容器中第一个值大于等于val 的元素的 iterator 位置
upper_bound(val) :返回容器中第一个值大于val 的元素的 iterator 位置