Super Mario
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2224 Accepted Submission(s): 1078
Problem Description
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.
Input
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 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.)
Output
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.
Sample Input
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
Sample Output
Case 1: 4 0 0 3 1 2 0 1 5 1
Source
Recommend
题意:给一n个数和m个询问L R H,询问[L, R]区间小于等于H的数的个数
一种方法是二分H在[L, R]的排名,用划分树
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#endif
#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)
const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));
const int maxn = 100000 + 20;
struct P_Tree {
int n, order[maxn];
int val[20][maxn], num[20][maxn];
LL sum[maxn], lsum[20][maxn], isum;
void init(int * A, int len) {
n = len;
sum[0] = 0;
for(int i=0; i<20; i++) val[i][0] = 0, num[i][0] = 0, lsum[i][0] = 0;
for(int i=1; i<=n; i++) {
order[i] = A[i];
val[0][i] = order[i];
sum[i] = sum[i-1] + order[i];
}
sort(order+1, order+1+n);
build(0, 1, n);
}
void build(int dept, int L, int R) {
if(L == R) return ;
int M = L + (R-L) / 2;
int same = M - L + 1;
int ln = L;
int rn = M+1;
for(int i=L; i<=R; i++)
if(val[dept][i] < order[M]) same--;
for(int i=L; i<=R; i++) {
int flag = 0;
if(val[dept][i] < order[M] || (val[dept][i] == order[M] && same)) {
flag = 1;
val[dept+1][ln++] = val[dept][i];
lsum[dept][i] = lsum[dept][i-1] + val[dept][i];
if(val[dept][i] == order[M]) same--;
} else {
val[dept+1][rn++] = val[dept][i];
lsum[dept][i] = lsum[dept][i-1];
}
num[dept][i] = num[dept][i-1] + flag;
}
build(dept+1, L, M);
build(dept+1, M+1, R);
}
int query(int dept, int L, int R, int st, int ed, int k) {
if(L == R) return val[dept][L];
int M = L + (R-L) / 2;
int lx = num[dept][st-1] - num[dept][L-1]; // [L, st-1]划到左边的数量
int ly = num[dept][ed] - num[dept][st-1]; // [st, ed]划到左边的数量
int rx = st-1 - L + 1 - lx; // [L, st-1]划到右边的数量
int ry = ed - st + 1 - ly; // [st, ed]划到右边的数量
if(ly >= k) return query(dept+1, L, M, L+lx, L+lx+ly-1, k);
else {
isum += lsum[dept][ed] - lsum[dept][st-1];
st = M + 1 + rx;
ed = M + 1 + rx + ry - 1;
return query(dept+1, M+1, R, st, ed, k-ly);
}
}
};
P_Tree tree;
int A[maxn];
int main() {
int T;
scanf("%d", &T);
for(int kase=1; kase<=T; kase++) {
int n, m;
printf("Case %d:\n", kase);
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++) {
scanf("%d", &A[i]);
}
tree.init(A, n);
for(int i=0; i<m; i++) {
int st, ed, h;
scanf("%d%d%d", &st, &ed, &h);
st++, ed++;
if(tree.query(0, 1, n, st, ed, ed-st+1) <= h) {
printf("%d\n", ed-st+1);
continue;
}
if(tree.query(0, 1, n, st, ed, 1) > h) {
puts("0");
continue;
}
int l = 1, r = ed-st+1;
int ans = 0;
while(l <= r) {
int mid = l + (r-l) / 2;
int t = tree.query(0, 1, n, st, ed, mid);
if(t > h) r = mid - 1;
else {
l = mid + 1;
ans = max(ans, mid);
}
}
printf("%d\n", ans);
}
}
return 0;
}
后面再补上