这里主要收录一些数据结构的模板
啊我还是太弱了居然要收录模板
1.树状数组

1 //树状数组
2 int a[],t[]//原数组,对应的树状数组
3 int lowbit(int x)
4 {
5 return x&(-x);
6 }
7 void modify(int x,int y)//单点修改a[x]加上y
8 {
9 for(int i=x;i<=n;i+=lowbit(i))
10 {
11 t[i]+=y;
12 }
13 }
14 int query(int x)//区间求和a[1]....a[x]
15 {
16 int ans=0;
17 for(int i=x;i>=1;i-=lowbit(i))
18 {
19 ans+=t[i];
20 }
21 return ans;
22 }
23 int sum(int l,int r)//区间求和a[l]....a[r]
24 {
25 return query(r)-query(l-1);
26 }
以及稍稍的变种

1 //区间修改,单点查询的树状数组,利用差分思想
2 #include<iostream>
3 #include<cstdio>
4 #include<cstring>
5 #include<cmath>
6 #include<algorithm>
7 using namespace std;
8 int a[1000001],b[1000001];
9 int m,n,x,y,z,q;
10 int lowbit(int x)
11 {
12 return x&(-x);
13 }
14 void add(int x,int y)
15 {
16 for(int i=x;i<=n;i+=lowbit(i))
17 a[i]+=y;
18 }
19 int sum(int s)
20 {
21 int ans=0;
22 for(int i=s;i>=1;i-=lowbit(i))
23 {
24 ans+=a[i];
25 }
26 return ans;
27 }
28 int main()
29 {
30 cin>>n>>m;
31 for(int i=1;i<=n;i++)
32 cin>>b[i];
33 for(int i=1;i<=m;i++)
34 {
35 cin>>x;
36 if(x==1)
37 {
38 cin>>y>>z>>q;
39 add(y,q);
40 add(z+1,-q);
41 }
42 if(x==2)
43 {
44 cin>>y;
45 printf("%lld\n",b[y]+sum(y));
46 }
47
48 }
49 }
2.线段树

1 struct pp
2 {
3 int l,r;
4 int sum;
5 int tag;
6 }f[];
7 void up(int rt)
8 {
9 f[rt].sum=f[rt<<1].sum+f[rt<<1|1].sum;
10 }
11 void down(int rt)
12 {
13 if(f[rt].tag)
14 {
15 f[rt<<1].sum+=f[rt].tag*(f[rt<<1].r-f[rt<<1].l+1);
16 f[rt<<1|1].sum+=f[rt].tag*(f[rt<<1|1].r-f[rt<<1|1].l+1);
17 f[rt<<1].tag+=f[rt].tag;
18 f[rt<<1|1].tag+=f[rt].tag;
19 f[rt].tag=0;
20 }
21 }
22 void build(int rt,int l,int r)
23 {
24 f[rt].l=l;
25 f[rt].r=r;
26 if(l==r)
27 {
28 f[rt].sum=a[l];
29 return;
30 }
31 int mid=(l+r)>>1;
32 build(rt<<1,l,mid);
33 build(rt<<1|1,mid+1,r);
34 up(rt);
35 }
36 void modify(int rt,int x,int y)
37 {
38 if(f[rt].l==f[rt].r)
39 {
40 f[rt].sum+=y;
41 return;
42 }
43 int mid=(f[rt].l+f[rt].r)>>1;
44 if(x<=mid) modify(rt<<1,x,y);
45 else/*if(x>mid)*/ modify(rt<<1|1,x,y);
46 up(rt);
47 }
48 void add(int rt,int l,int r,int k)
49 {
50 if(l<=f[rt].l&&f[rt].r<=r)
51 {
52 f[rt].sum+=k*(f[rt].r-f[rt].l+1);
53 f[rt].tag+=k;
54 return;
55 }
56 int ans=0;
57 down(rt);
58 int mid=(f[rt].l+f[rt].r)>>1;
59 if(l<=mid) add(rt<<1,l,r,k);
60 if(r>mid) add(rt<<1|1,l,r,k);
61 up(rt);
62 }
63 int query(int rt,int l,int r)
64 {
65 if(l<=f[rt].l&&f[rt].r<=r)
66 {
67 return f[rt].sum;
68 }
69 down(rt);
70 int ans=0;
71 int mid=(f[rt].l+f[rt].r)>>1;
72 if(l<=mid) ans+=query(rt<<1,l,r);
73 if(r>mid) ans+=query(rt<<1|1,l,r);
74 return ans;
75 }
以及线段树的区间乘法

1 //线段树取模与区间乘法LAZYTAG
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<algorithm>
6 #include<iostream>
7 using namespace std;
8 struct pp
9 {
10 int l,r;
11 long long sum,add,mul;
12 }f[5000005];
13 int a[1000001];
14 int x,y,z,k,n,m,p;
15 void up(int rt)
16 {
17 f[rt].sum=(f[rt<<1].sum+f[rt<<1|1].sum)%p;
18 }
19 void down(int rt) {
20 if(f[rt].add!=0||f[rt].mul!=1) {
21 int mid = (f[rt].l + f[rt].r) >> 1;
22 f[rt<<1].sum=(f[rt<<1].sum*f[rt].mul+f[rt].add*(mid-f[rt].l+1))%p;
23 f[rt<<1|1].sum=(f[rt<<1|1].sum*f[rt].mul+f[rt].add*(f[rt].r-mid))%p;
24 f[rt<<1].mul=(f[rt<<1].mul*f[rt].mul)%p;
25 f[rt<<1|1].mul=(f[rt<<1|1].mul*f[rt].mul)%p;
26 f[rt<<1].add=(f[rt<<1].add*f[rt].mul+f[rt].add)%p;
27 f[rt<<1|1].add=(f[rt<<1|1].add*f[rt].mul+f[rt].add)%p;
28 f[rt].add=0;
29 f[rt].mul=1;
30 }
31 }
32
33 //void down(int rt)
34 //{
35 // if(f[rt].add!=0||f[rt].mul!=1)
36 // {
37 // f[rt<<1].sum=(f[rt<<1].sum*f[rt].mul+f[rt].add*(f[rt].r-f[rt].l+1))%p;
38 // f[rt<<1|1].sum=(f[rt<<1|1].sum*f[rt].mul+f[rt].add*(f[rt].r-f[rt].l+1))%p;
39 // f[rt<<1].mul=(f[rt<<1].mul*f[rt].mul)%p;
40 // f[rt<<1|1].mul=(f[rt<<1|1].mul*f[rt].mul)%p;
41 // f[rt<<1].add=(f[rt<<1].add*f[rt].mul+f[rt].add)%p;
42 // f[rt<<1|1].add=(f[rt<<1|1].add*f[rt].mul+f[rt].add)%p;
43 // f[rt].add=0;
44 // f[rt].mul=1;
45 // }
46 //}
47 void build(int rt,int l,int r)
48 {
49 f[rt].add=0;
50 f[rt].mul=1;
51 f[rt].l=l;
52 f[rt].r=r;
53 if(l==r){
54 f[rt].sum=a[l];
55 return ;
56
57 }
58 int mid=(l+r)>>1;
59 build(rt<<1,l,mid);
60 build(rt<<1|1,mid+1,r);
61 up(rt);
62 }
63 void mult(int rt,int l,int r,int k)
64 {
65 if(l<=f[rt].l&&r>=f[rt].r)
66 {
67 f[rt].sum=(f[rt].sum*k)%p;
68 f[rt].mul=(f[rt].mul*k)%p;
69 f[rt].add=(f[rt].add*k)%p;
70 return;
71 }
72 down(rt);
73 int mid=(f[rt].l+f[rt].r)>>1;
74 if(l<=mid) mult(rt<<1,l,r,k);
75 if(r>mid) mult(rt<<1|1,l,r,k);
76 up(rt);
77 }
78 void quer(int rt,int l,int r,int k)
79 {
80 if(l<=f[rt].l&&r>=f[rt].r)
81 {
82 f[rt].sum=(f[rt].sum+k*(f[rt].r-f[rt].l+1))%p;
83 f[rt].add=(f[rt].add+k)%p;
84 return;
85 }
86 down(rt);
87 int mid=(f[rt].l+f[rt].r)>>1;
88 if(l<=mid) quer(rt<<1,l,r,k);
89 if(r>mid) quer(rt<<1|1,l,r,k);
90 up(rt);
91 }
92 long long sum (int rt,int l,int r)
93 {
94 if(l<=f[rt].l&&r>=f[rt].r){
95 return f[rt].sum%p;
96 }
97 down(rt);
98 long long ans=0;
99
100 int mid=(f[rt].r+f[rt].l)>>1;
101 if(l<=mid) ans+=sum(rt<<1,l,r);
102 if(mid<r) ans+=sum(rt<<1|1,l,r);
103 return ans%p;
104 }
105 int main(){
106
107 scanf("%d%d%d",&n,&m,&p);
108 for(int i=1;i<=n;i++)
109 scanf("%d",&a[i]);
110 build(1,1,n);
111 for(int i=1;i<=m;i++){
112 scanf("%d",&x);
113 if(x==1){
114 scanf("%d%d%d",&y,&z,&k);
115 mult(1,y,z,k);
116 }
117 else if(x==2){
118 scanf("%d%d%d",&y,&z,&k);
119 quer(1,y,z,k);
120 }
121 else{
122 scanf("%d%d",&y,&z);
123 cout<<sum(1,y,z)<<endl;
124 }
125 }
126 return 0;
127 }
3.树链剖分
这里用线段树来维护并操作树剖

1 #include <iostream>
2 #include <cstdio>
3 #include <algorithm>
4 #include <cstring>
5 #include <cmath>
6 using namespace std;
7 const int MAXN=200010;
8 struct pp
9 {
10 int u;
11 int nex;
12 }e[MAXN];
13 struct oo
14 {
15 int l,r;
16 int sum,tag;
17 }s[MAXN];
18 int n,m,cnt,g,mod,res,num;
19 int head[MAXN],a[MAXN],wt[MAXN];
20 int id[MAXN],son[MAXN],dep[MAXN],sz[MAXN],top[MAXN],fa[MAXN];
21 void add(int x ,int y)
22 {
23 e[++cnt].u=y;
24 e[cnt].nex=head[x];
25 head[x]=cnt;
26 }
27 // 线段树
28 void up(int rt)
29 {
30 s[rt].sum=(s[rt<<1].sum+s[rt<<1|1].sum)%mod;
31 }
32 void down(int rt)
33 {
34 if(s[rt].tag)
35 {
36 s[rt<<1].sum=(s[rt<<1].sum+s[rt].tag*(s[rt<<1].r-s[rt<<1].l+1))%mod;
37 s[rt<<1|1].sum=(s[rt<<1|1].sum+s[rt].tag*(s[rt<<1|1].r-s[rt<<1|1].l+1))%mod;
38 s[rt<<1].tag=(s[rt<<1].tag+s[rt].tag)%mod;
39 s[rt<<1|1].tag=(s[rt<<1|1].tag+s[rt].tag)%mod;
40 s[rt].tag=0;
41 }
42 }
43 void build(int rt,int l,int r)
44 {
45 s[rt].l=l;
46 s[rt].r=r;
47 if(l==r)
48 {
49 s[rt].sum=a[l];
50 return;
51 }
52 int mid=(l+r)>>1;
53 build(rt<<1,l,mid);
54 build(rt<<1|1,mid+1,r);
55 up(rt);
56 }
57 void modify(int rt,int l,int r,int v)
58 {
59 if(l<=s[rt].l&&r>=s[rt].r)
60 {
61 s[rt].sum=(s[rt].sum+v*(s[rt].r-s[rt].l+1))%mod;
62 s[rt].tag=(s[rt].tag+v)%mod;
63 return ;
64 }
65 down(rt);
66 int mid=(s[rt].l+s[rt].r)>>1;
67 if(l<=mid) modify(rt<<1,l,r,v);
68 if(r>mid) modify(rt<<1|1,l,r,v);
69 up(rt);
70 }
71 int querry(int rt,int l,int r)
72 {
73 if(l<=s[rt].l&&r>=s[rt].r)
74 {
75 return s[rt].sum;
76 }
77 down(rt);
78 int ans=0;
79 int mid=(s[rt].r+s[rt].l)>>1;
80 if(l<=mid) ans=(ans+querry(rt<<1,l,r))%mod;
81 if(r>mid) ans=(ans+querry(rt<<1|1,l,r))%mod;
82 return ans;
83 }
84 //线段树
85 void dfs1(int x,int f,int deep)
86 {
87 dep[x]=deep;
88 fa[x]=f;
89 sz[x]=1;
90 int maxson=-1;
91 for(int i=head[x];i;i=e[i].nex)
92 {
93 int y=e[i].u;
94 if(y==f) continue;
95 dfs1(y,x,deep+1);
96 sz[x]+=sz[y];
97 if(sz[y]>maxson){
98 maxson=sz[y];
99 son[x]=y;
100 }
101 }
102 }
103 void dfs2(int x,int tt)
104 {
105 id[x]=++num;
106 a[num]=wt[x];
107 top[x]=tt;
108 if(!son[x]) return;
109 dfs2(son[x],tt);
110 for(int i=head[x];i;i=e[i].nex)
111 {
112 int y=e[i].u;
113 if(y==fa[x]||y==son[x]) continue;
114 dfs2(y,y);
115 }
116 }
117 int q1(int x,int y)
118 {
119 int ans=0;
120 while(top[x]!=top[y])
121 {
122 if(dep[top[x]]<dep[top[y]]) swap(x,y);
123 ans+=querry(1,id[top[x]],id[x]);
124 ans%=mod;
125 x=fa[top[x]];
126 }
127 if(dep[x]<dep[y]) swap(x,y);
128 ans+=querry(1,id[y],id[x]);
129 return ans%mod;
130 }
131 void tree_add(int x,int y,int v)
132 {
133 while(top[x]!=top[y])
134 {
135 if(dep[top[x]]<dep[top[y]]) swap(x,y);
136 modify(1,id[top[x]],id[x],v%mod);
137 x=fa[top[x]];
138 }
139 if(dep[x]<dep[y]) swap(x,y);
140 modify(1,id[y],id[x],v);
141 }
142 int son_add(int x,int v)
143 {
144 modify(1,id[x],id[x]+sz[x]-1,v%mod);
145 }
146 int son_querry(int x)
147 {
148 return querry(1,id[x],id[x]+sz[x]-1);
149 }
150 int main()
151 {
152 scanf("%d%d%d%d",&n,&m,&g,&mod);
153 for(int i=1;i<=n;i++) scanf("%d",&wt[i]);
154 for(int i=1;i<=n-1;i++)
155 {
156 int a,b;
157 scanf("%d%d",&a,&b);
158 add(a,b);
159 add(b,a);
160 }
161 dfs1(g,0,1);
162 dfs2(g,g);
163 build(1,1,n);
164 while(m--)
165 {
166 int aa,bb,cc,dd;
167 scanf("%d",&aa);
168 if(aa==1)
169 {
170 scanf("%d%d%d",&bb,&cc,&dd);
171 dd=dd%mod;
172 tree_add(bb,cc,dd);
173 }
174 else if(aa==2)
175 {
176 scanf("%d%d",&bb,&cc);
177 dd=q1(bb,cc);
178 printf("%d\n",dd);
179 }
180 else if(aa==3)
181 {
182 scanf("%d%d",&bb,&cc);
183 son_add(bb,cc);
184 }
185 else
186 {
187 scanf("%d",&bb);
188 cc=son_querry(bb);
189 printf("%d\n",cc);
190 }
191 }
192 return 0;
193 }
