问题 H: Boring Counting
时间限制: 3 Sec 内存限制: 128 MB
题目描述
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.
样例输入 Copy
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
样例输出 Copy
Case #1:
13
7
3
6
9
题意:
给定一个长度为n的序列和m次询问,每次询问给出L,R,A,B,问在下标为[ L,R ] 的序列里,满足A<=X<=B的X有多少个。
思路:
如果我们知道A是第几个数,B是第几个数,就能计算出在A和B之间有多少个数。
对于求区间第K大的值,可以用主席树求;现在是知道值求该值是区间的第几个数,可以用二分来做。
需要注意判断一下A和B之间没有数的情况。
代码:
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll>PLL;
typedef pair<int,int>PII;
typedef pair<double,double>PDD;
#define I_int ll
#define x first
#define y second
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
char F[200];
inline void out(I_int x) {
if (x == 0) return (void) (putchar('0'));
I_int tmp = x > 0 ? x : -x;
if (x < 0) putchar('-');
int cnt = 0;
while (tmp > 0) {
F[cnt++] = tmp % 10 + '0';
tmp /= 10;
}
while (cnt > 0) putchar(F[--cnt]);
//cout<<" ";
}
ll ksm(ll a,ll b,ll p){ll res=1;while(b){if(b&1)res=res*a%p;a=a*a%p;b>>=1;}return res;}
const int inf=0x3f3f3f3f,mod=1000000007;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn=1e5+7,maxm=3e5+7;
const double PI = atan(1.0)*4;
int n,m;
int a[maxn];
vector<int>nums;
struct node{
int l,r,cnt;
}tr[maxn*20];
int root[maxn],idx;
int Find(int x){
return lower_bound(nums.begin(),nums.end(),x)-nums.begin();
}
int build(int l,int r){
int p=++idx;
if(l==r) return p;
int mid=(l+r)>>1;
tr[p].l=build(l,mid);tr[p].r=build(mid+1,r);
return p;
}
int Insert(int p,int l,int r,int x){
int q=++idx;
tr[q]=tr[p];
if(l==r){
tr[q].cnt++;
return q;
}
int mid=(l+r)>>1;
if(x<=mid) tr[q].l=Insert(tr[p].l,l,mid,x);
else tr[q].r=Insert(tr[p].r,mid+1,r,x);
tr[q].cnt=tr[tr[q].l].cnt+tr[tr[q].r].cnt;
return q;
}
int qask(int q, int p, int l, int r, int k)
{
if (l == r) return r;
int cnt = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
int mid=(l+r)>>1;
if (k <= cnt) return qask(tr[q].l, tr[p].l, l, mid, k);
else return qask(tr[q].r, tr[p].r, mid + 1, r, k - cnt);
}
int main(){
int T=read();
for(int Case=1;Case<=T;Case++){
printf("Case #%d:\n",Case);
nums.clear();idx=0;
memset(tr,0,sizeof tr);memset(root,0,sizeof root);
n=read(),m=read();
for(int i=1;i<=n;i++){
a[i]=read();nums.push_back(a[i]);
}
sort(nums.begin(),nums.end());
nums.erase(unique(nums.begin(), nums.end()), nums.end());
root[0]=build(0,nums.size()-1);
for(int i=1;i<=n;i++)
root[i]=Insert(root[i-1],0,nums.size()-1,Find(a[i]));
while(m--){
int l=read(),r=read(),A=read(),B=read();
///int tmp=qask(root[r],root[l-1],0,nums.size()-1,k);区间第k大
int res=0;
bool flag=0;
int la=1,ra=r-l+1,resa=-1;
while(la<=ra){
int mid=(la+ra)>>1;
int tmp=qask(root[r],root[l-1],0,nums.size()-1,mid);
if(nums[tmp]>=A) ra=mid-1,resa=mid;
else la=mid+1;
}
if(resa==-1) flag=1;
else res=res-resa+1;
int lb=1,rb=r-l+1,resb=-1;
while(lb<=rb){
int mid=(lb+rb)>>1;
int tmp=qask(root[r],root[l-1],0,nums.size()-1,mid);
if(nums[tmp]<=B) lb=mid+1,resb=mid;
else rb=mid-1;
}
if(resb==-1) flag=1;
else res=res+resb;
if(flag) res=0;
///cout<<resa<<" "<<resb<<endl;
out(res);puts("");
}
}
return 0;
}