牛客國慶2 C.Just h-index(主席樹)

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章