https://ac.nowcoder.com/acm/contest/1107/C
題意:求最大的K,滿足條件區間內大於K的個數也得大於等於K,
題解:比賽時瞎搞,二分+主席樹 按照大於K的個數是否滿足條件去二分,主席樹查個數
結束後看其他人代碼,發現可以直接找第K大,在樹上查詢本來就是二分查找的,可以塊一個二分的複雜度(註釋部分代碼)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int a[maxn];
struct node{
int l,r;
int num;
int sum;
}T[maxn*50];
int root[maxn],cnt;
int n,q;
void update(int l,int r,int &x,int y,int pos){
T[++cnt]=T[y];
T[cnt].sum++;
x=cnt;
if(l==r) return ;
int mid=(l+r)/2;
if(pos<=mid) update(l,mid,T[x].l,T[y].l,pos);
else update(mid+1,r,T[x].r,T[y].r,pos);
}
int query(int l,int r,int L,int R,int pl,int pr){
if(T[R].sum-T[L].sum==0) return 0;
if(pl<=l&&r<=pr){
return T[R].sum-T[L].sum;
}
int mid=(l+r)/2;
int ans=0;
if(pl<=mid) ans+=query(l,mid,T[L].l,T[R].l,pl,pr);
if(pr>mid) ans+=query(mid+1,r,T[L].r,T[R].r,pl,pr);
return ans;
}
bool check(int l,int r,int k){
int tmp=query(1,n,root[l-1],root[r],k,n);
if(tmp>=k) return 1;
else return 0;
}
//int query2(int suf,int l,int r,int r1,int r2){
// if(l==r){
// return l;
// }
// int s=T[T[r2].r].sum-T[T[r1].r].sum;
// int mid=(l+r)>>1;
// if(s+suf>=mid+1) return query2(suf,mid+1,r,T[r1].r,T[r2].r);
// else return query2(s+suf,l,mid,T[r1].l,T[r2].l);
//}
int main(){
while(scanf("%d%d",&n,&q)!=EOF){
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
update(1,n,root[i],root[i-1],a[i]);
}
while(q--){
int l,r; scanf("%d%d",&l,&r);
int ll=1; int rr=r-l+1;
int ans=0;
while(ll<=rr){
int mid=(ll+rr)/2;
if(check(l,r,mid)){
ans=max(ans,mid);
ll=mid+1;
}else{
rr=mid-1;
}
}
printf("%d\n",ans);
}
//方法2
// while(q--) {
// int l,r; scanf("%d%d",&l,&r);
// int ans=query2(0,1,n,root[l-1],root[r]);
// printf("%d\n",ans);
// }
}
return 0;
}