主席树 - 孤独·粲泽 - 博客园 (cnblogs.com)
题解里面那个式子手推一下就可以发现它的巧妙!!
主席树算法的讲解还可看我校前辈在哔站上的算法讲堂
注意root[i],ls[o],rs[o]中记录的都是节点编号!!!而非节点权值!!!
1 #include <cstdio> 2 #include <cmath> 3 #include <cstdlib> 4 #include <cstring> 5 #include <queue> 6 #include <stack> 7 #include <vector> 8 #include <iostream> 9 #include "algorithm" 10 #define lson l,m 11 #define rson m+1,r 12 #define mem(a,b) memset(a,b,sizeof(a)) 13 using namespace std; 14 const int MAX=3e5+5; 15 int n,q,tot; 16 int root[MAX],sum[MAX<<5],ls[MAX<<5],rs[MAX<<5]; 17 inline int read(){ 18 int an(0),x=1;char c=getchar(); 19 while (c<'0' || c>'9') {if (c=='-') x=-1;c=getchar();} 20 while (c>='0' && c<='9') {an=(an<<3)+(an<<1)+c-'0';c=getchar();} 21 return an*x; 22 } 23 void build(int preo,int &o,int l,int r,int val){ 24 o=++tot; 25 ls[o]=ls[preo],rs[o]=rs[preo],sum[o]=sum[preo]+1; 26 if (l==r) return; 27 int m=(l+r)>>1; 28 if (val<=m) build(ls[preo],ls[o],lson,val); 29 else build(rs[preo],rs[o],rson,val); 30 } 31 int query(int lo,int ro,int l,int r,int val){ 32 if (l==r) return sum[ro]-sum[lo]; 33 int ans,m=(l+r)>>1; 34 if (sum[ls[ro]]-sum[ls[lo]]>=val) 35 return query(ls[lo],ls[ro],lson,val); 36 else return query(rs[lo],rs[ro],rson,val-(sum[ls[ro]]-sum[ls[lo]])); 37 } 38 int main(){ 39 freopen ("a.in","r",stdin); 40 freopen ("a.out","w",stdout); 41 int i,j,x,y,ans,k,m; 42 n=read();q=read(); 43 tot=0; 44 mem(root,0),mem(ls,0),mem(rs,0),mem(sum,0); 45 for (i=1;i<=n;i++){ 46 x=read(); 47 build(root[i-1],root[i],1,n,x); 48 } 49 for (i=1;i<=q;i++){ 50 x=read();y=read(); 51 m=y-x+1; if (m%2) m++; 52 k=query(root[x-1],root[y],1,n,m/2); 53 if (k<=m/2) printf("1\n"); 54 else printf("%d\n",2*k-(y-x+1)); 55 } 56 return 0; 57 }