sdutoj 2610 Boring Counting

时间:2023-03-09 01:26:41
sdutoj 2610 Boring Counting

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2610

Boring Counting

Time Limit: 3000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

    In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence. Now you task is to answer a list of queries, for each query, please tell us among [L, R], how many Pi is not less than A and not greater than B( L<= i <= R). In other words, your task is to count the number of Pi (L <= i <= R,  A <= Pi <= B).

输入

     In the first line there is an integer T (1 < T <= 50), indicates the number of test cases. 
     For each case, the first line contains two numbers N and M (1 <= N, M <= 50000), the size of sequence P, the number of queries. The second line contains N numbers Pi(1 <= Pi <= 10^9), the number sequence P. Then there are M lines, each line contains four number L, R, A, B(1 <= L, R <= n, 1 <= A, B <= 10^9)

输出

    For each case, at first output a line ‘Case #c:’, c is the case number start from 1. Then for each query output a line contains the answer.

示例输入

1
13 5
6 9 5 2 3 6 8 7 3 2 5 1 4
1 13 1 10
1 13 3 6
3 6 3 6
2 8 2 8
1 9 1 9

示例输出

Case #1:
13
7
3
6
9

提示

来源

 2013年山东省第四届ACM大学生程序设计竞赛

示例程序

分析:

题意是说给你一串数字,求在动态区间[L , R]内的在[A , B]范围内的数的个数。

数据很大,一般的方法会超。

官方标程:

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm> using namespace std; #define lson l, m, rt->left
#define rson m + 1, r, rt->right const int maxn = ; struct Node {
int sum;
Node *left, *right;
}*root[maxn], tree[], *idx; int num[maxn], p[maxn], mp[maxn];
int n, m;
int tol; inline Node* nextNode() {
idx->sum = ;
idx->left = idx->right = NULL;
return idx++;
} inline Node* copyNode(Node* temp) {
idx->sum = temp->sum;
idx->left = temp->left;
idx->right = temp->right;
return idx++;
} inline bool cmp(int a, int b) {
return num[a] < num[b];
} void input() {
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) {
scanf("%d", &num[i]);
p[i] = i;
}
sort(p + , p + n + , cmp);
int pre = -0x7f7f7f7f;
tol = ;
for(int i = ; i <= n; i++) {
if(num[ p[i] ] == pre) {
num[ p[i] ] = tol;
}
else {
pre = num[ p[i] ];
mp[ ++tol ] = num[ p[i] ];
num[ p[i] ] = tol;
}
}
} void build(int l, int r, Node* rt) {
if(l == r) return;
int m = (l + r) >> ;
rt->left = nextNode();
rt->right = nextNode();
build(lson);
build(rson);
} int query(int ll, int rr, int l, int r, Node* rtl, Node* rtr) {
if(ll <= l && r <= rr) {
return rtr->sum - rtl->sum;
}
int m = (l + r) >> ;
int ret = ;
if(ll <= m) ret += query(ll, rr, l, m, rtl->left, rtr->left);
if(rr > m) ret += query(ll, rr, m + , r, rtl->right, rtr->right);
return ret;
} Node* add(int x, int l, int r, Node* rt) {
Node* temp = copyNode(rt);
if(l == r) {
temp->sum++;
return temp;
}
int m = (l + r) >> ;
if(x <= m) temp->left = add(x, lson);
else temp->right = add(x, rson);
temp->sum = temp->left->sum + temp->right->sum;
return temp;
} void build() {
idx = tree;
root[] = nextNode();
build(, tol, root[]);
for(int i = ; i <= n; i++) {
root[i] = add(num[i], , tol, root[i - ]);
}
} inline int bin1(int x) { //find the left-most number that is >= x
int left = , right = tol;
int ans = -;
while(left <= right) {
int mid = (left + right) >> ;
if(mp[mid] >= x) {
ans = mid;
right = mid - ;
}
else left = mid + ;
}
return ans;
} inline int bin2(int x) { // find the right-most number that is <= x
int left = , right = tol;
int ans = -;
while(left <= right) {
int mid = (left + right) >> ;
if(mp[mid] <= x) {
ans = mid;
left = mid + ;
}
else right = mid - ;
}
return ans;
} void solve() {
static int cas = ;
printf("Case #%d:\n", cas++);
while(m--) {
int l, r, a, b;
scanf("%d%d%d%d", &l, &r, &a, &b);
a = bin1(a);
b = bin2(b);
if(a == - || b == -) {
puts("");
continue;
}
printf("%d\n", query(a, b, , tol, root[l - ], root[r]));
}
} int main() {
//freopen("input.in", "r", stdin);
//freopen("output.out", "w", stdout); int __t;
scanf("%d", &__t);
while(__t--) {
input();
build();
solve();
}
return ;
}