NC19427 换个角度思考

链接:https://ac.nowcoder.com/acm/problem/19427
来源:牛客网

题目描述

给定一个序列,有多次询问,每次查询区间里小于等于某个数的元素的个数
即对于询问 (l,r,x),你需要输出 ∑i=lr[ai≤x]\sum_{i=l}^{r}[a_i \le x]∑i=lr​[ai​≤x] 的值
其中 [exp] 是一个函数,它返回 1 当且仅当 exp 成立,其中 exp 表示某个表达式

输入描述:

第一行两个整数n,m
第二行n个整数表示序列a的元素,序列下标从1开始标号,保证1 ≤ ai ≤ 105
之后有m行,每行三个整数(l,r,k),保证1 ≤ l ≤ r ≤ n,且1 ≤ k ≤ 105

输出描述:

对于每一个询问,输出一个整数表示答案后回车

思路

根据题意我们知道要询问的是区间内小于等于k的个数。

首先我们想区间问题的处理一般会选择树或者树状数组,然后我们去思考如何去解决这个问题。

询问中 ( l , r , k ) (l,r,k) (l,r,k)询问在区间内小于等于 k k k的个数,我们考虑到可以离线处理

我们将原数组的结构体和询问的结构体排序后,按询问的 k k k的大小进行插入,每次插入的都是小于询问的 k k k,然后去区间和求解。

然后树状数组就可以在 n log ⁡ n n\log n nlogn的复杂度内求出答案。

#include
#define INF 0x3f3f3f3f
#define DOF 0x7f7f7f7f
#define endl '\n'
#define mem(a,b) memset(a,b,sizeof(a))
#define debug(case,x); cout<
#define open freopen("ii.txt","r",stdin)
#define close freopen("oo.txt","w",stdout)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<long long, long long> PII;
const int maxn = 1e6+10;
int n,m;
//int a[maxn];
int d[maxn];
int ans[maxn];
struct node{
    int a,id;
    bool operator<(const node x)const{
        if(id==x.id) return id<x.id;
        else return a<x.a;
    }
}node[maxn];
struct section{
    int l,r,k,id;
    bool operator<(const section x)const {
        return k<x.k;
    }
}section[maxn];
inline int lowbit(int x){return x&(-x);}

int get_sum(int x){
    int ans=0;
    while(x){
        ans+=d[x];x-=lowbit(x);
    }
    return ans;
}

void update(int x,int y){
    while(x<=n){
        d[x]+=y;x+=lowbit(x);
    }
}


int main(){
    cin>>n>>m;
    for(int i=1;i<=n;++i){
        cin>>node[i].a;
        node[i].id=i;
    }
    int l,r,k;
    for(int i=1;i<=m;++i){
        cin>>l>>r>>k;
        section[i]={l,r,k,i};
    }
    sort(node+1,node+1+n);
    sort(section+1,section+1+m);

    for(int i=1,j=1;i<=m;++i){
        int val=section[i].k;
        for(;j<=n&&node[j].a<=val;++j){
            update(node[j].id,1);
        }
        ans[section[i].id]=get_sum(section[i].r)-get_sum(section[i].l-1);
    }
    for(int i=1;i<=m;++i){
        cout<<ans[i]<<endl;
    }

}

你可能感兴趣的:(题解)