Hdu 6278 主席樹
阿新 • • 發佈:2018-11-14
這道題就是求區間內第K大的數必須小於等於K,主席樹求區間K大以後二分求答案就行
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+5; struct Node{ int l,r,sum; }tree[maxn*20]; int a[maxn],tot=0,root[maxn]; vector<int>v; void build(int l,int r) { int now=++tot; tree[now].sum=0; if(l==r) return ; int mid=(l+r)/2; tree[now].l=tot+1;build(l,mid); tree[now].r=tot+1;build(mid+1,r); } void update(int pre,int l,int r,int x) { int now=++tot; tree[now]=tree[pre];tree[now].sum++; if(l==r) return ; int mid=(l+r)/2; if(x<=mid) { tree[now].l=tot+1; update(tree[pre].l,l,mid,x); } else { tree[now].r=tot+1; update(tree[pre].r,mid+1,r,x); } } int query(int l,int r,int L,int R,int k) { if(l==r) return l; int mid=(l+r)/2,temp=tree[tree[R].l].sum-tree[tree[L].l].sum; if(k<=temp) return query(l,mid,tree[L].l,tree[R].l,k); else return query(mid+1,r,tree[L].r,tree[R].r,k-temp); } int main() { ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); int n,m; while(cin>>n>>m) { tot=0;v.clear(); for(int i=1;i<=n;i++) cin>>a[i],v.push_back(a[i]); sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); root[0]=1;build(1,n); for(int i=1;i<=n;i++) { root[i]=tot+1; int id=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1; update(root[i-1],1,n,id); } for(int i=1;i<=m;i++) { int l,r;cin>>l>>r; int ansl=1,ansr=r-l+2,ans=0; while(ansl<ansr) { int mid=(ansl+ansr)/2; int k=r-l+1-mid+1; int id=query(1,n,root[l-1],root[r],k); if(v[id-1]>=mid) { ans=max(ans,mid);ansl=mid+1; } else ansr=mid; } cout<<ans<<"\n"; } } return 0; }
學了一下主席樹感覺也不是很難,哎好多東西都是因為第一眼看上去太難了就不想去學