• 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),然后去区间和求解。

    然后树状数组就可以在(nlog n)的复杂度内求出答案。

    #include<bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define DOF 0x7f7f7f7f
    #define endl '
    '
    #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;
        }
    
    }
    
    
  • 相关阅读:
    ubuntu16.04搭建jdk1.8运行环境
    window如何查看被占用端口的使用情况
    Windows下80端口被进程System占用的解决方法
    java.lang.OutOfMemoryError:PermGen space tomcat7 内存溢出
    GitLab服务器IP地址修改
    Ubuntu输入ifconfig找不到IP地址,只有lo问题
    git命令如何删除文件或文件夹
    数组转List
    Java NIO 缓冲区
    MySQL数据类型-整型
  • 原文地址:https://www.cnblogs.com/waryan/p/13339731.html
Copyright © 2020-2023  润新知