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;
}

浙公网安备 33010602011771号