2025牛客寒假集训营 F,可以用主席树,也可以用树状数组(线段树)+离线处理,并且用树状数组代码更短更好写,只是当时第一次见这种建树思路,没开出来。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int,int>;
using db = double;
const int N=2e5+10;
struct node{
    int l,r;
    int sum;
}tree[N<<5];
#define ls(x) tree[x].l
#define rs(x) tree[x].r
int n,m;
int a[N],b[N],root[N];//root为第i棵线段树的根节点编号
int cnt;
void build(int &x,int l,int r){
    x=++cnt;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(ls(x),l,mid);
    build(rs(x),mid+1,r);
}
void insert(int x,int &y,int l,int r,int v){
    y=++cnt;
    tree[y]=tree[x];
    tree[y].sum++;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(v<=mid) insert(ls(x),ls(y),l,mid,v);
    else insert(rs(x),rs(y),mid+1,r,v);
}
int query(int x,int y,int l,int r,int k){
    if(l==r) return l;
    int mid=(l+r)>>1;
    int s=tree[ls(y)].sum-tree[ls(x)].sum;
    if(k<=s) return query(ls(x), ls(y), l, mid, k);
    else return query(rs(x), rs(y), mid+1, r, k-s);
}
int main(){
    std::ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        b[i]=a[i];
    }
    sort(b+1,b+1+n);
    int size=unique(b+1,b+1+n)-(b+1);
    build(root[0], 1, size);
    for(int i=1;i<=n;i++){
        int x=lower_bound(b+1,b+1+size,a[i])-b;
        insert(root[i-1],root[i],1,size,x);
    }
    while(m--){
        int x,y,k;
        cin>>x>>y>>k;
        int t=query(root[x-1], root[y], 1, size, k);
        cout<<b[t]<<endl;
    }
    return 0;
}

树状数组+离线处理代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int,int>;
using db = double;
#define lowbit(x) ((x)&-(x))
int n,m;
const int N=3e5+10;
int a[N];
int tree[N];
int num[N];
int ans[N];
void update(int x,int d,int n){
    while(x<=n){
        tree[x]+=d;
        x+=lowbit(x);
    }
}
int sum(int x,int n){
    int ans=0;
    while(x>0){
        ans+=tree[x];
        x-=lowbit(x);
    }
    return ans;
}
int main(){
    std::ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int t;
    cin>>t;
    while(t--){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            a[i]=0;
            tree[i]=0;
            num[i]=0;
        }
        for(int i=1;i<=n;i++){
            cin>>a[i];
            num[a[i]]=i;
        }
        map<int,vector<array<int,3>>> mp;
        for(int i=1;i<=m;i++){
            int l,r,c;
            cin>>l>>r>>c;
            mp[c].push_back({l,r,i});
        }
        for(int i=1;i<=n;i++){
            int pos=num[i];
            update(pos,1,n);
            if(!mp.count(pos)) continue;
            for(auto v:mp[pos]){
                int l=v[0],r=v[1],tmp=v[2];
                ans[tmp]=sum(r,n)-sum(l-1,n)+l-1;
            }
        }
        for(int i=1;i<=m;i++){
            cout<<ans[i]<<endl;
        }
    }
    return 0;
}