Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble again and Mario needs to save his lover. We regard the road to the boss’s castle as a line (the length is n), on every integer point i there is a brick on height hi. Now the question is how many bricks in [L, R] Mario can hit if the maximal height he can jump is H.
The first line follows an integer T, the number of test data.
For each test data:
The first line contains two integers n, m (1 <= n <=10^5, 1 <= m <= 10^5), n is the length of the road, m is the number of queries.
Next line contains n integers, the height of each brick, the range is [0, 1000000000].
Next m lines, each line contains three integers L, R,H.( 0 <= L <= R < n 0 <= H <= 1000000000.)
For each case, output "Case X: " (X is the case number starting from 1) followed by m lines, each line contains an integer. The ith integer is the number of bricks Mario can hit for the ith query.
1
10 10
0 5 2 7 5 4 3 8 7 7
2 8 6
3 5 0
1 3 1
1 9 4
0 1 0
3 5 5
5 5 1
4 6 3
1 5 7
5 7 3
Case 1:
4
0
0
3
1
2
0
1
5
1
要求我们求出在给定区间内求出有多少个数比H小。
1 首先就是主席树的模板打出来,需要修改的地方就是在查找一部分。
2 之前打的基本就是找第k小的数,但是这个就不一样了,这是找比k小的数,所以我们就要找到比k大的数的位置,这样就求出了第k小的数了,然后就是求出有多少个数。
3 如果k会比这个区间全部的都来的大,那么直接输出两个线段树的相减就行了,如果是在左边找左边,否则就加上左边的然后往右边找。
!!!需要注意的几个地方:
1 初始化
2 如果建树区间如果是从1开始的,在查询的时候区间要加上一。
3 如果是第k小的数位置是0,那么就说明没有数字比k来的小,直接输出0就行了,否则容易TLE。
#include
#include
#include
#include
using namespace std;
const int maxn = 1e+5 + 10;
struct NODE {
int l;
int r;
int sum;
};
NODE T[maxn * 50];
int root[maxn], a[maxn];
int cnt = 0;
vector v;
int GetId(int x) {
return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}
void Updata(int l, int r, int &x, int y, int pos) {
T[++cnt] = T[y];
T[cnt].sum++;
x = cnt;
if (l == r) return ;
int mid = (l + r) >> 1;
if (mid >= pos) Updata(l, mid, T[x].l, T[y].l, pos);
else Updata(mid + 1, r, T[x].r, T[y].r, pos);
}
int Query(int l, int r, int x, int y, int k) {
if (r <= k) return T[y].sum - T[x].sum;
int mid = (l + r) >> 1;
if (k <= mid) return Query(l, mid, T[x].l, T[y].l, k);
else return T[T[y].l].sum - T[T[x].l].sum + Query(mid + 1, r, T[x].r, T[y].r, k);
}
int main() {
int t, n, m;
scanf("%d", &t);
for (int Case = 1; Case <= t; Case++) {
printf("Case %d:\n", Case);
v.clear();
cnt = 0;
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
v.push_back(a[i]);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
for (int i = 1; i <= n; i++) Updata(1, n, root[i], root[i - 1], GetId(a[i]));
while (m--) {
int x, y, k;
scanf("%d %d %d", &x, &y, &k);
x++;
y++;
int temp = upper_bound(v.begin(), v.end(), k) - v.begin();
if (temp) printf("%d\n", Query(1, n, root[x - 1], root[y], temp));
else printf("0\n");
}
}
return 0;
}