UESTC2021暑假前集训(主席树)

UESTC2021暑假前集训(主席树)

 

 UESTC2021暑假前集训(主席树)

 

 UESTC2021暑假前集训(主席树)

 

 主席树 - 孤独·粲泽 - 博客园 (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 }

 

上一篇:最大子序和、最长上升子序列长度


下一篇:编辑距离