https://blog.csdn.net/qq_39653331/article/details/78816987
https://www.cnblogs.com/zyf0163/p/4749042.html
感觉都写的好好,但是还是没有完全弄懂,目前只是懂了一点点QAQ,还是太菜了
然后贴上最近刷的几道题的代码吧
hdu 4417 Super Mario
1 #include<cstdio>
2 #include<cstring>
3 #include<cmath>
4 #include<iostream>
5 #include<algorithm>
6 using namespace std;
7 #define N 100005
8
9 int root[N];//root[i]表示第i课线段树
10 int size[N*25],lchild[N*25],rchild[N*25];
11 int tot;
12
13 void insert(int last,int cur,int L,int R,int k) //单点更新
14 {
15 size[cur]=size[last]+1;//将前一个树的信息复制过来
16 lchild[cur]=lchild[last];
17 rchild[cur]=rchild[last];
18 if(L==R)return ;
19 int mid=L+R>>1;
20 if(k<=mid) insert(lchild[last],lchild[cur]=++tot,L,mid,k);//对于需要更改的节点都需要新增节点
21 else insert(rchild[last],rchild[cur]=++tot,mid+1,R,k);
22 }
23 int query(int last,int cur,int l,int r,int L,int R)
24 {
25 if(l>r)return 0;
26 if(L==l&&r==R){
27 return size[cur]-size[last];
28 }
29 int mid=(L+R)>>1;
30 if(l>mid)return query(rchild[last],rchild[cur],l,r,mid+1,R);
31 else if(r<=mid)return query(lchild[last],lchild[cur],l,r,L,mid);
32 else return query(rchild[last],rchild[cur],mid+1,r,mid+1,R)+query(lchild[last],lchild[cur],l,mid,L,mid);
33 }
34 int a[100005];
35 int b[100005];
36 int main(){
37 int t;
38 scanf("%d",&t);
39 int c=1;
40 while(t--){
41 int n,m;
42 scanf("%d%d",&n,&m);
43 for(int i=1;i<=n;i++){
44 scanf("%d",&a[i]);
45 b[i]=a[i];
46 }
47 sort(b+1,b+n+1);//排序
48 int nn=unique(b+1,b+n+1)-b-1;//去重
49 //上面是在离散化处理
50 tot=0;
51 for(int i=1;i<=n;i++){
52 int k=lower_bound(b+1,b+nn+1,a[i])-b;//找到a[i]在整个数列中是第几大
53 insert(root[i-1],root[i]=++tot,1,nn,k);
54 }
55 printf("Case %d:\n",c++);
56 for(int i=1;i<=m;i++){
57 int l,r,h;
58 scanf("%d%d%d",&l,&r,&h);
59 l++;r++;
60 int k=upper_bound(b+1,b+1+nn,h)-b-1;//找到h在整个数列中是第几大
61 printf("%d\n",query(root[l-1],root[r],1,k,1,nn));
62 }
63 }
64 return 0;
65 }
P3567 [POI2014]KUR-Couriers
1 #include<cstdio>
2 #include<algorithm>
3 #include<cstring>
4 #include<vector>
5 using namespace std;
6 const int N=5e5+6;
7 int n,m,cnt,root[N],a[N],x,y,k;
8 struct node
9 {
10 int l,r,sum;
11 }T[N*40];
12 vector<int>v;
13 int getid(int x)
14 {
15 return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
16 }
17 void update(int l,int r,int &x,int y,int pos)
18 {
19 T[++cnt]=T[y];
20 T[cnt].sum++;
21 x=cnt;
22 if(l==r)
23 return ;
24 int mid=(l+r)>>1;
25 if(mid>=pos)
26 update(l,mid,T[x].l,T[y].l,pos);
27 else
28 update(mid+1,r,T[x].r,T[y].r,pos);
29 }
30 int query(int l,int r,int x,int y,int k)
31 {
32 if(l==r)
33 return l;
34 int mid=(l+r)>>1;
35 int sum1=T[T[y].l].sum-T[T[x].l].sum;
36 int sum2=T[T[y].r].sum-T[T[x].r].sum;
37 if(sum1+sum1>k)
38 return query(l,mid,T[x].l,T[y].l,k);
39 if(sum2+sum2>k)
40 return query(mid+1,r,T[x].r,T[y].r,k);
41 return 0;
42 }
43 int main()
44 {
45 scanf("%d%d",&n,&m);
46 for(int i=1;i<=n;i++)
47 {
48 scanf("%d",&a[i]);
49 update(1,n,root[i],root[i-1],a[i]);
50 }
51 for(int i=1;i<=m;i++)
52 {
53 scanf("%d%d",&x,&y);
54 printf("%d\n",query(1,n,root[x-1],root[y],y-x+1));
55 }
56 return 0;
57 }
POJ 2104 K-th Number 主席树
1 #include<cstdio>
2 #include<algorithm>
3 #include<cstring>
4 #include<vector>
5 using namespace std;
6 const int N=1e5+6;
7 int n,m,cnt,root[N],a[N],x,y,k;
8 struct node
9 {
10 int l,r,sum;
11 }T[N*40];
12 vector<int>v;
13 int getid(int x)
14 {
15 return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
16 }
17 void update(int l,int r,int &x,int y,int pos)
18 {
19 T[++cnt]=T[y];
20 T[cnt].sum++;
21 x=cnt;
22 if(l==r)
23 return ;
24 int mid=(l+r)>>1;
25 if(mid>=pos)
26 update(l,mid,T[x].l,T[y].l,pos);
27 else
28 update(mid+1,r,T[x].r,T[y].r,pos);
29 }
30 int query(int l,int r,int x,int y,int k)
31 {
32 if(l==r)
33 return l;
34 int mid=(l+r)>>1;
35 int sum=T[T[y].l].sum-T[T[x].l].sum;
36 if(sum>=k)
37 return query(l,mid,T[x].l,T[y].l,k);
38 else
39 return query(mid+1,r,T[x].r,T[y].r,k-sum);
40 }
41 int main()
42 {
43 scanf("%d%d",&n,&m);
44 for(int i=1;i<=n;i++)
45 {
46 scanf("%d",&a[i]);
47 v.push_back(a[i]);
48 }
49 sort(v.begin(),v.end());
50 v.erase(unique(v.begin(),v.end()),v.end());
51 for(int i=1;i<=n;i++)
52 {
53 update(1,n,root[i],root[i-1],getid(a[i]));
54 }
55 for(int i=1;i<=m;i++)
56 {
57 scanf("%d%d%d",&x,&y,&k);
58 printf("%d\n",v[query(1,n,root[x-1],root[y],k)-1]);
59 }
60 return 0;
主席树模板
1 #include <bits/stdc++.h>
2 using namespace std ;
3 bool Read ( int &x ) ///输入挂
4 {
5 char c = getchar() ; x = 0 ; bool f = 0 ;
6 while ( !isdigit(c) )
7 {
8 if ( c == '-' ) f = 1 ;
9 if ( c == EOF ) return false ; c = getchar() ;
10 }
11 while ( isdigit(c) )
12 { x = 10 * x + c - '0' ; c = getchar() ; }
13 if (f) x = -x ;return true ;
14 }
15 void Print ( int x ) ///输出挂
16 {
17 int len=0,a[50] ;
18 if ( x == 0 ) { putchar('0') ; return ; }
19 if ( x < 0 ) { putchar('-') ; x = -x ; }
20 while (x) { a[++len] = x%10 ; x /= 10 ; }
21 while (len) putchar(a[len--]+'0') ;
22 }
23
24 const int maxn=200010 ;
25 int n,m,rt[maxn],Rank[maxn],cnt ;
26 struct node
27 {
28 int l, r, v ;
29 } tree[maxn<<5] ;
30 struct nodd
31 {
32 int v, id ;
33 friend bool operator < ( nodd a, nodd b )
34 {
35 return a.v == b.v ? a.id < b.id : a.v < b.v ;
36 }
37 } a[maxn] ;
38 ///这个k是数据key,不是第k大,x前面有一个取地址
39 void insert ( int K, int& x, int l, int r )
40 {///这个是调用过程:insert(Rank[i],rt[i],1,n) ;
41 tree[++cnt]=tree[x] ;
42 x=cnt;///把rt[i]指向了rt[++cnt]这个真的根节点
43 tree[x].v++;///增加数量
44 int mid =(l+r)>>1 ;
45 if(l==r)return ;
46 if(K<=mid) insert(K,x[tree].l,l,mid) ;
47 else insert(K,x[tree].r,mid+1,r) ;///节点的编号机制不是*2和*2+1
48 ///而是根据调用次数由cnt管控,所以要存在每一个节点里
49 }
50
51 int query ( int rt1, int rt2, int l, int r, int K )
52 {
53 if ( l == r ) return l ;
54 int mid = l+r >> 1 ;
55 int num = tree[rt2].l[tree].v - tree[rt1].l[tree].v ;
56 /**可加减性,为啥这样做,因为几点存的是前缀和,
57 我们要特定区间就把前面的减去咯。
58 你也可以这样认为:假设查第999大,当前节点总共管3个数,
59 你就需要把前面没用的减去咯。*/
60 if ( K <= num )
61 return query ( rt1[tree].l, rt2[tree].l, l, mid, K ) ;
62 else
63 return query ( rt1[tree].r, rt2[tree].r, mid+1, r, K-num ) ;
64 }
65
66 int main()
67 {
68 int i,j,k,x,y;
69 Read(n) ; Read(m) ;
70 for (i=1;i<=n;i++) ///离散
71 {
72 Read(a[i].v) ;
73 a[i].id=i ;
74 }
75 sort (a+1,a+n+1) ;
76 for (i=1;i<=n;i++)
77 Rank[a[i].id]=i ;
78
79 for (i=1;i<=n;i++)
80 {
81 rt[i]=rt[i-1] ;
82 /**
83 一开始有棵空树,不这样写,直接传root[1],
84 当需要递归到不需要改的区间,无法找到初试树的位置,
85 所以暂且把初试树的root完全复制过来
86 这样,因为每一棵树的根节点存储了它儿子的标号,
87 所以这一步相当于第1棵树完全等价与第0棵树,
88 只多开了一个root,其他的已经!!完全检索!!到上一棵树里
89 然后在新的树里把不一样的树枝修改成新的值,
90 并且新开空间就行了
91 所以之后递归就是if,else if,只选择一条路,
92 以此类推,第i棵树继承第i-1棵树就行了
93 */
94 insert(Rank[i],rt[i],1,n);
95 }
96
97 while(m--)
98 {
99 Read(x);Read(y);Read(k) ;
100 Print(a[query(rt[x-1],rt[y],1,n,k)].v ) ;
101 putchar('\n') ;
102 }
103
104 return 0 ;
105 }