Loading

CF840D-主席树

CF840D-主席树

给定一个无修改的区间,对于m次区间询问,给出出现次数严格大于(r-l+1)/k的最小数。

主席树(权值线段树)的结构刚好可以比较容易地处理这个问题。

我们首先对数值建立权值线段树(由于数值可能比较大需要先离散化处理)维护离散后的数值范围的出现次数,然后以在原区间的下标为根节点逐步插入形成一棵主席树,这样以rt[l-1]和rt[r]为根的两棵树对应节点之间的差值就是询问的[l,r]区间内的数值的出现次数。

查询出现次数大于k次的最小点,只需要先往左节点查找,若size≤k则返回-1并查找右节点,size>k则递归地在左节点中继续查找。最后l==r时判断这个权值的出现次数是否大于k即可。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsinged long long
#define ld long double
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
#define debugg(x) cout<<#x<<"="<<x<<endl;
#define debug1(x,y,z) cout<<#x<<' '<<x<<' '<<#y<<' '<<y<<' '<<#z<<' '<<z<<endl;
#define debug cout<<endl<<"*********"<<endl;
#define itn int
#define pii pair<int,int>
//#define mid ((all[now].lo+all[now].ro)/2)
#define mod m1
void fre(){
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
}
void fc(){fclose(stdin);fclose(stdout);}
const int maxn=1e5+10;
const ll inf=0x3f3f3f3f;
int n,m,tot;
int yuan[maxn],rt[maxn],lisan[maxn];
struct node{
    int lo;int ro;int zhi;
}all[maxn*20];
void pushup(int now,int lo,int ro){all[now].zhi=all[lo].zhi+all[ro].zhi;}
void build(int &now,int lo,int ro){
    if(now==0) now=++tot;
    if(lo==ro) return;
    int mid=(lo+ro)/2;
    build(all[now].lo,lo,mid);
    build(all[now].ro,mid+1,ro);
}
void inser(int &now,int rnow,int lo,int ro,int pos){
    now=++tot;all[now]=all[rnow];
    if(lo==ro){all[now].zhi=all[rnow].zhi+1;return;}
    int mid=(lo+ro)/2;
    if(pos<=mid) inser(all[now].lo,all[rnow].lo,lo,mid,pos);
    else inser(all[now].ro,all[rnow].ro,mid+1,ro,pos);
    pushup(now,all[now].lo,all[now].ro);
}
int query(int rnow1,int rnow2,int lo,int ro,int zhi){
    if(all[rnow2].zhi-all[rnow1].zhi<=zhi) return -1;
    if(lo==ro){
        if(all[rnow2].zhi-all[rnow1].zhi>zhi) return lo;
        else return -1;
    }
    int mid=(lo+ro)/2;
    int ans1=-1,ans2=-1;
    if(all[all[rnow2].lo].zhi-all[all[rnow1].lo].zhi>zhi) ans1=query(all[rnow1].lo,all[rnow2].lo,lo,mid,zhi);
    if(ans1==-1) ans2=query(all[rnow1].ro,all[rnow2].ro,mid+1,ro,zhi);
    if(ans1!=-1) return ans1;
    else return ans2;
}
int main(){
    ios;fre();
    cin>>n>>m;
    for(int i=1;i<=n;i++){cin>>yuan[i];lisan[i]=yuan[i];}
    sort(yuan+1,yuan+1+n);
    int k=unique(yuan+1,yuan+1+n)-yuan-1;
    build(rt[0],1,k);
    for(int i=1;i<=n;i++){
        int res=lower_bound(yuan+1,yuan+1+k,lisan[i])-yuan;
        inser(rt[i],rt[i-1],1,k,res);
    }
    for(int i=1;i<=m;i++){
        int a1,a2,a3;cin>>a1>>a2>>a3;
        int ans=query(rt[a1-1],rt[a2],1,k,(a2-a1+1)/a3);
        if(ans==-1) cout<<-1<<endl;
        else cout<<yuan[ans]<<endl;
    }
    return 0;
}
posted @ 2021-03-26 10:38  14long  阅读(61)  评论(0)    收藏  举报