UPC组队赛第四场—— H: Boring Counting (主席树+二分)

简介: UPC组队赛第四场—— H: Boring Counting (主席树+二分)

问题 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;
}

参考博客

目录
相关文章
|
8月前
|
人工智能
POJ 2299 Ultra-QuickSort(树状数组+离散化+求逆序数)
POJ 2299 Ultra-QuickSort(树状数组+离散化+求逆序数)
|
11月前
51nod 1711 平均数(二分 + 树状数组好题)
51nod 1711 平均数(二分 + 树状数组好题)
75 0
UPC-探险(线段树+二分)
UPC-探险(线段树+二分)
57 0
|
SQL Shell
HDU-4348 To the moon(主席树区间修改 永久化标记)
HDU-4348 To the moon(主席树区间修改 永久化标记)
116 0
HDU-4348 To the moon(主席树区间修改 永久化标记)
|
机器学习/深度学习 人工智能 算法
CF1446D Frequency Problem(思维 前缀和 根号分治 双指针)
CF1446D Frequency Problem(思维 前缀和 根号分治 双指针)
64 0
|
人工智能
【待补】UPC No Need(二分+bitset || 背包dp)
【待补】UPC No Need(二分+bitset || 背包dp)
40 0
UPC-喜爱(打表+二分)
UPC-喜爱(打表+二分)
61 0
UPC-喜爱(打表+二分)
|
机器学习/深度学习 存储 人工智能
UPC 小澳的葫芦 (最短路+01分数规划 )
UPC 小澳的葫芦 (最短路+01分数规划 )
81 0
PTA -7-51 两个有序链表序列的合并(C++)
已知两个非降序链表序列S1与S2,设计函数构造出S1与S2合并后的新的非降序链表S3。 输入格式: 输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。 输出格式: 在一行中输出合并后新的非降序链表,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL。 输入样例: 1 3 5 -1 2 4 6 8 10 -1 输出样例: 1 2 3 4 5 6 8 10
503 0
|
机器学习/深度学习
[POJ] John‘s trip | 欧拉回路 | 边序列字典序最小 + 建图
Description Little Johnny has got a new car. He decided to drive around the town to visit his friends. Johnny wanted to visit all his friends, but there was many of them. In each street he had one friend. He started thinking how to make his trip as short as possible.
121 0
[POJ] John‘s trip | 欧拉回路 | 边序列字典序最小 + 建图

热门文章

最新文章