首页 > 技术文章 > 数据结构模板

xwx2354672579 2019-08-26 19:34 原文

这里主要收录一些数据结构的模板

 啊我还是太弱了居然要收录模板 

 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 }
树链剖分

 

推荐阅读