【BZOJ】3524 [POI2014] Couriers(主席树)
题目
传送门:QWQ
传送到洛谷QWQ
分析
把求区间第k大的改一改就ok了。
代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=500010; 4 int root[N*40], ls[N*40], rs[N*40], sum[N*40]; 5 int n, m, newp; 6 7 void add(int l,int r,int x,int& cur,int cur1) 8 { 9 cur=++newp; 10 ls[cur]=ls[cur1]; rs[cur]=rs[cur1]; sum[cur]=sum[cur1]+1; 11 if(l==r) return; int mid=l+r>>1; 12 if(x<=mid) add(l,mid,x,ls[cur],ls[cur1]); 13 else add(mid+1,r,x,rs[cur],rs[cur1]); 14 } 15 16 int query(int l,int r,int k,int cur,int cur1) 17 { 18 if(l==r) return l; 19 int mid=l+r>>1, cmp1=sum[ls[cur1]]-sum[ls[cur]], cmp2=sum[rs[cur1]]-sum[rs[cur]]; 20 if(cmp1>k) return query(l,mid,k,ls[cur],ls[cur1]); 21 else if(cmp2>k) return query(mid+1,r,k,rs[cur],rs[cur1]); 22 return 0; 23 } 24 25 int main() 26 { 27 scanf("%d%d",&n,&m); 28 for(int i=1;i<=n;i++) 29 { 30 int x; scanf("%d",&x); 31 add(1,n,x,root[i],root[i-1]); 32 } 33 34 for(int i=1;i<=m;i++) 35 { 36 int l,r; scanf("%d%d",&l,&r); 37 printf("%d\n",query(1,n,r-l+1>>1,root[l-1],root[r])); 38 } 39 return 0; 40 }