1. 程式人生 > 實用技巧 >NC19427 換個角度思考

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)\)詢問在區間內小於等於\(k\)的個數,我們考慮到可以離線處理

我們將原陣列的結構體和詢問的結構體排序後,按詢問的\(k\)的大小進行插入,每次插入的都是小於詢問的\(k\),然後去區間和求解。

然後樹狀陣列就可以在\(n\log n\)的複雜度內求出答案。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define DOF 0x7f7f7f7f
#define endl '\n'
#define mem(a,b) memset(a,b,sizeof(a))
#define debug(case,x); cout<<case<<"  : "<<x<<endl;
#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;
    }

}