ACM模板 - 持续更新中

快速幂

 1 typedef long long ll;
 2 
 3 ll mod_pow(ll x,ll n,ll mod)
 4 {
 5     ll res=1;
 6     while(n>0)
 7     {
 8         if(n&1)//if(n%2==1)
 9             res=res*x%mod;
10         x=x*x%mod;//把x平方
11         n>>=1;//n=n/2 舍去最后一位
12     }
13     return res;
14 }
View Code

如果用来取模的数本身很大,快速幂会爆掉的话,加上快速乘来优化时间,以达到大数相乘取模:

 1 typedef long long ll;
 2 ll mod_pow(ll x,ll n,ll mod)
 3 {
 4     ll res=1;
 5     while(n>0)
 6     {
 7         if(n&1)
 8             res = mod_mulit(res,x,mod);
 9         x = mod_multi(x,x,mod);
10         n >>= 1;
11     }
12     return res;
13 }
View Code

  

树状数组

查询区间和

引申:查询区间最值差

 1 int lowbit(int x)//lowbit(x)表示2^k
 2 {
 3     return x&(-x);
 4 }
 5 
 6 void update(int x,int k)//在位置x增加k
 7 {
 8     while(x<=n)
 9     {
10         c[x]+=k;
11         x+=lowbit(x);
12     }
13 }
14 
15 int sum(int x)
16 {
17     int res=0;
18     while(x>0)
19     {
20         res+=c[x];
21         x-=lowbit(x);
22     }
23     return res;
24 }
25 
26 memset(c,0,sizeof(c));//输入记得清空
27 
28 for(int i=1; i<=n; i++)//树状数组处理的是下标为1的数组
29 {
30     scanf("%d",&a[i]);
31     update(i,a[i]);//开始的时候每个元素初始值为0,对应位置加a[i]即可
32 }
View Code

 

最长公共子序列问题

 1 char/int a[55],b[55];
 2 int dp[55][55];//dp若是太大,就利用滚动数组取余处理
 3 int lcs()
 4 {
 5     //(char)
 6     int la=strlen(a);
 7     int lb=strlen(b);
 8     for(int i=0;i)
 9     {
10         for(int j=0;j)
11         {
12             if(a[i]==b[j])
13                 dp[i+1][j+1]=dp[i][j]+1;//两个数组整体往后挪一位
14             else
15                 dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
16         }
17     }
18     return dp[la][lb];
19 }
View Code

 

欧几里得算法(辗转相除法)

可以调用__gcd(a,b);
或者自己写函数:

1 int gcd(int a,int b)
2 {
3     if(b==0)
4         return a;
5     return(b,a%b);
6 }
View Code

 ACM模板 - 持续更新中_第1张图片

 

扩展欧几里得

求ax+by=gcd(a,b)的整数解x、y,同时可以求出最大公因数

 1 int exgcd(int a,int b,int &x,int &y)
 2 {
 3     if(b==0)
 4     {
 5         x=1,y=0;
 6         return a;
 7     }
 8     int yin=exgcd(b,a%b,x,y);
 9     int t=x;
10     x=y;
11     y=t-(a/b)*y;
12     //x1=y2, 
13     //y1=x2-(a/b)*y2; 
14     return yin;
15 }  
16 
17 int main()
18 {
19     int a,b,x,y;
20     scanf("%d %d",&a,&b);
21     int maxx=exgcd(a,b,x,y);//最大公因数 
22     return 0;
23 }
View Code

 

扩展欧几里得求逆元

ACM模板 - 持续更新中_第2张图片

 

以上两种解法均要满足a、p互质。 

 

逆元定义:a*x ≡ 1 (mod p)  满足a乘以x对p取模等于1 ,此时称 x为a对p的逆元。

     只有a与p互质才有逆元 ,互质即gcd(a,p)=1

 问法:

求 :(a/b)%p;

转化成 (a*x)%p    (即需要求b的逆元x) ;

即bx≡1modp;

设一个未知数y,则有bx+py=1(x即为所求逆元)(简介化成扩展欧几里得问题,因为b、p互质,所以gcd(b,p)=1 )。

 

如何求解:

1 int inverse(int b,int p)//求b的逆元x 
2 {
3     int d=ex_gcd(b,p,x,y);//这里面的参数x就是所求逆元
4     if(d==1)
5         return (x%p+p)%p;
6     //防止逆元为负,若需要负数作为逆元则return x即可
7     return -1;//逆元不存在则返回-1
8 }

 

Dijkstra:

 1 void  dijkstra()
 2 {
 3     memset(book,0,sizeof(book));
 4     for(int i=1;i<=n;i++)
 5         dis[i]=e[1][i];
 6     book[1]=1;
 7     int u;
 8     for(int i=2;i<=n;i++)
 9     {
10         int minn=inf;
11         for(int j=1;j<=n;j++)
12         {
13             if(book[j]==0&&dis[j]<minn)
14             {
15                 u=j;
16                 minn=dis[j];
17             }
18         }
19         book[u]=1;
20         for(int k=1;k<=n;k++)
21         {
22             if(e[u][k]dis[k])
23             {
24                 dis[k]=dis[u]+e[u][k];
25             }
26         }
27     }
28 }
View Code

 

kruskal:

  1 //kruskal
  2 #include
  3 #include<string.h>
  4 #include
  5 #include
  6 #include
  7 #include
  8 #include
  9 #include
 10 using namespace std;
 11 #define inf 0x3f3f3f3f
 12 #define inff 0x3f3f3f3f3f3f3f3f
 13 const int N=2200;
 14 #define mod 998244353
 15 typedef long long ll;
 16 
 17 int f[N];
 18 char a[N][10];
 19 
 20 struct node
 21 {
 22     int l,r,d;
 23 } e[N*N];
 24 
 25 int getf(int x)
 26 {
 27     if(f[x]==x)
 28         return x;
 29     return f[x]=getf(f[x]);
 30 }
 31 
 32 int merge(int x,int y)
 33 {
 34     int t1=getf(x);
 35     int t2=getf(y);
 36     if(t1!=t2)
 37     {
 38         f[t2]=t1;
 39         return 1;
 40     }
 41     return 0;
 42 }
 43 
 44 bool cmp1(node x,node y)
 45 {
 46     return x.d<y.d;
 47 }
 48 int main()
 49 {
 50     ios::sync_with_stdio(false);
 51     int n;
 52     while(cin>>n)
 53     {
 54         if(n==0)
 55             break;
 56         memset(e,0,sizeof(e));
 57         /*for(int i=1;i<=n;i++)
 58         {
 59             for(int j=1;j<=n;j++)
 60             {
 61                 if(i==j)
 62                     e[i][j]=0;
 63                 else
 64                     e[i][j]=inf;
 65             }
 66         }*/
 67         for(int i=1; i<=n; i++)
 68         {
 69             scanf("%s",a[i]);
 70             f[i]=i;
 71         }
 72         int p=0;
 73         for(int i=1; i<=n; i++)
 74         {
 75             for(int j=1; j<=n; j++)
 76                 //for(int j=i+1; j<=n; j++)
 77             {
 78                 int sum=0;
 79                 for(int k=0; k<7; k++)
 80                 {
 81                     if(a[i][k]!=a[j][k])
 82                         sum++;
 83                 }
 84                 //e[i][j]=e[j][i]=sum;
 85                 e[p].l=i;
 86                 e[p].r=j;
 87                 e[p++].d=sum;
 88             }
 89         }
 90         int w,ans=0;
 91         sort(e,e+p,cmp1);
 92         for(int i=0; i)
 93         {
 94             if(merge(e[i].l,e[i].r)==1)
 95             {
 96                 w++;
 97                 ans+=e[i].d;
 98             }
 99             if(w==n-1)
100                 break;
101         }
102         cout<<"The highest possible quality is 1/"<"."<<endl;
103     }
104     return 0;
105 }
View Code

 

prim:

 1 //prim
 2 #include
 3 #include<string.h>
 4 #include
 5 #include
 6 #include
 7 #include
 8 #include
 9 #include
10 using namespace std;
11 #define inf 0x3f3f3f3f
12 #define inff 0x3f3f3f3f3f3f3f3f
13 const int N=2200;
14 #define mod 998244353
15 typedef long long ll;
16 
17 int e[N][N],dist[N];
18 int n,ans;
19 bool book[N];
20 char a[N][10];
21 
22 void prim()
23 {
24     int countt=1;//countt代表点数,而不是边数
25     ans=0;//记录路径长度
26     for(int i=1;i<=n;i++)
27     {
28         dist[i]=e[1][i];
29         book[i]=0;
30     }
31     book[1]=1;
32     while(countt<n)
33     {
34         int minn=inf,u;
35         for(int i=1;i<=n;i++)
36         {
37             if(!book[i]&&dist[i]<minn)
38             {
39                 minn=dist[i];
40                 u=i;
41             }
42         }
43         ans+=minn;
44         countt++;
45         book[u]=1;
46         for(int i=1;i<=n;i++)
47         {
48             if(!book[i]&&dist[i]>e[u][i])
49             {
50                 dist[i]=e[u][i];
51             }
52         }
53     }
54 
55 }
56 int main()
57 {
58     ios::sync_with_stdio(false);
59     while(cin>>n)
60     {
61         if(n==0)
62             break;
63         for(int i=1;i<=n;i++)
64         {
65             for(int j=1;j<=n;j++)
66             {
67                 if(i==j)
68                     e[i][j]=0;
69                 else
70                     e[i][j]=inf;
71             }
72         }
73         for(int i=1; i<=n; i++)
74             scanf("%s",a[i]);
75         for(int i=1; i<=n; i++)
76         {
77             for(int j=1; j<=n; j++)
78                 //for(int j=i+1; j<=n; j++)
79             {
80                 int sum=0;
81                 for(int k=0; k<7; k++)
82                 {
83                     if(a[i][k]!=a[j][k])
84                         sum++;
85                 }
86                 e[i][j]=e[j][i]=sum;
87             }
88         }
89         prim();
90         cout<<"The highest possible quality is 1/"<"."<<endl;
91     }
92     return 0;
93 }
View Code

 

最短路和最小生成树区别:

最小生成树能够保证整个拓扑图的所有路径之和最小,但不能保证任意两点之间是最短路径。
最短路径是从一点出发,到达目的地的路径最小。

 

网络流

 1 #include
 2 #include<string.h>
 3 #include
 4 #include
 5 using namespace std;
 6 #define inf 0x3f3f3f3f
 7 const int N=220;
 8 
 9 int e[N][N],pre[N];
10 int n,m,s,t;
11 bool book[N];
12 int maxflow;
13 
14 
15 bool bfs()
16 {
17     memset(book,false,sizeof(book));
18     memset(pre,0,sizeof(pre));
19     queue<int>Q;
20     Q.push(s);
21     book[s]=true;
22 
23    while(!Q.empty())
24     {
25         int p=Q.front();
26         Q.pop();
27         if(p==t)
28             return true;
29         for(int i=1; i<=n; i++)
30         {
31             if(book[i]==false)
32             {
33                 if(e[p][i]>0)
34                 {
35                     book[i]=true;
36                     pre[i]=p;
37                     Q.push(i);
38                 }
39             }
40         }
41     }
42     return false;
43 }
44 
45 
46 int solve()
47 {
48     maxflow=0;
49     while(1)
50     {
51         if(bfs()==false)
52             return maxflow;
53         int minn=inf;
54         for(int i=t; i!=s; i=pre[i])
55             minn=min(minn,e[pre[i]][i]);
56         for(int i=t; i!=s; i=pre[i])
57         {
58             e[pre[i]][i]-=minn;
59             e[i][pre[i]]+=minn;
60         }
61         maxflow+=minn;
62     }
63 }
64 
65 int main()
66 {
67     int u,v,w;
68     int tt=1,ttt;
69     {
70         while(~scanf("%d %d",&m,&n))
71         {
72             memset(e,0,sizeof(e));
73             s=1,t=n;
74             for(int i=1; i<=m; i++)
75             {
76                 scanf("%d %d %d",&u,&v,&w);
77                 e[u][v]+=w;
78             }
79             printf("%d\n",solve());
80         }
81     }
82     return 0;
83 }
View Code

 

kmp 

查找模式串在原串中出现了几次

 1 char s[10020],t[1000020];
 2 int lens,lent;
 3 int nextt[10020];
 4 void getnext()
 5 {
 6     int i=0,j=-1;
 7     nextt[0]=-1;
 8     while(i<lens)
 9     {
10         if(j<0||s[i]==s[j])
11         {
12             nextt[++i]=++j;
13         }
14         else
15             j=nextt[j];
16     }
17 }
18 
19 int kmp()
20 {
21     int i=0,j=0,ans=0;
22     while(i<lent)
23     {
24         if(j<0||t[i]==s[j])
25         {
26             i++;
27             j++;
28         }
29         else
30             j=nextt[j];
31         if(j==lens)
32         {
33             ans++;
34             j=nextt[j];
35         }
36     }
37     return ans;
38 }
View Code

 

0-1背包

 1 //HDU-4508
 2 #include
 3 #include<string.h>
 4 #include
 5 using namespace std;
 6 int dp[2000000];
 7 int main()
 8 {
 9     int w[110],v[110];
10     int n,i,m,j;
11     while(~scanf("%d",&n))
12     {
13         memset(dp,0,sizeof(dp));
14         for(i=0;i)
15         {
16             scanf("%d %d",&w[i],&v[i]);
17         }//w幸福值 价值 v卡路里 重量
18         scanf("%d",&m);
19         for(i=0;i)
20         {
21             for(j=v[i];j<=m;j++)
22             {
23                 dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
24             }
25         }
26         printf("%d\n",dp[m]);
27     }
28     return 0;
29 }
View Code

 

SPFA

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #include
 7 #include
 8 #include<string.h>
 9 
10 using namespace std;
11 #define men(p,b) memset(p,b,sizeof(p))
12 #define inf 0x3f3f3f3f
13 typedef long long ll;
14 
15 const int N=5020;
16 bool book[N];;
17 int n,dis1[N],dis2[N],head[N*10],tot;
18 struct node
19 {
20     int u,v,w,nextt;
21 }e[260000];
22 
23 void add(int u,int v,int w)
24 {
25     e[tot].u=u;
26     e[tot].v=v;
27     e[tot].w=w;
28     e[tot].nextt=head[u];
29     head[u]=tot++;
30 }
31 
32 void SPFA(int x,int*dis)
33 {
34     for(int i=1;i<=n;i++)
35     {
36 //       book[i]=0;
37         dis[i]=inf;
38     }
39     book[x]=1;
40     dis[x]=0;
41     queue<int> Q;
42     Q.push(x);
43     while(!Q.empty())
44     {
45         int u=Q.front();
46         Q.pop();
47         book[u]=0;
48         for(int i=head[u];i!=-1;i=e[i].nextt)
49         {
50             int u=e[i].u,v=e[i].v,w=e[i].w;
51             if(dis[v]>dis[u]+w)
52             {
53                 dis[v]=dis[u]+w;
54                 if(!book[v])
55                 {
56                     book[v]=1;
57                     Q.push(v);
58                 }
59             }
60         }
61     }
62 }
63 
64 
65 int main()
66 {
67     int r;
68     cin>>n>>r;
69     memset(head,-1,sizeof(head));
70     tot=0;
71     for(int i=1;i<=r;i++)
72     {
73         int x,y,z;
74         scanf("%d %d %d",&x,&y,&z);
75         add(x,y,z);
76         add(y,x,z);
77     }
78     SPFA(1,dis1);//1到其他所有点的最短距离
79     SPFA(n,dis2);//n到其他所有点的最短距离
80     int minn=inf;
81     for(int i=1;i<=2*r;i++)
82     {
83         int u=e[i].u,v=e[i].v,w=e[i].w;
84         if(dis1[u]+dis2[v]+w>dis1[n])
85             minn=min(minn,dis1[u]+dis2[v]+w);
86     }
87     cout<endl;
88     return 0;
89 }
View Code

 

线段树区间修改(A->B)、查询

  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 #include
  8 #include<string.h>
  9 
 10 using namespace std;
 11 #define mem(p,b) memset(p,b,sizeof(p))
 12 #define inf 0x3f3f3f3f
 13 typedef long long ll;
 14 
 15 const int N=1e5+20;
 16 ll a[N<<2],lazy[N<<2];//需要开到节点的四倍大小
 17 
 18 void build(int L,int R,int i)
 19 {
 20     if(L==R)//当左右结点相同的时候,说明该节点可以建树,输入即可。
 21     {
 22         scanf("%lld",&a[i]);//即为叶子结点
 23         return;//因为已经确定这个点可以输入了,也就类似叶结点,返回函数上次调用的地方即可。
 24     }
 25 
 26     //否则往下继续找
 27     int mid=(L+R)>>1;
 28     build(L,mid,i<<1);//递归建立左子树
 29     build(mid+1,R,i<<1|1);//递归建立右子树
 30     a[i]=a[i<<1]+a[i<<1|1];//统计该点(i)的左子树和右子树之和
 31     //a这个操作也可以另外写到一个函数pushup中(即pushup(i)),这个看自己怎么写代码
 32     //节点数据向上更新
 33 
 34     //根据题意写,这一题是求区间和,之前左区间和右区间相加即可
 35     //例如如果求区间内最大值,则写成:a[i]=max(a[i<<1],a[i<<1|1]);
 36 }
 37 
 38 void pushdown(int i,int len)//节点懒惰标记下推
 39 {
 40     if(lazy[i])//如果懒惰标记为真,说明之前有过懒惰标记,现在需要进行更新
 41     {
 42 //        lazy[i<<1]+=lazy[i];//懒惰标记往左结点传
 43 //        lazy[i<<1|1]+=lazy[i];//懒惰标记往右结点传
 44 //        //左右用 |1 区分
 45 //        //因为求区间和,所以当区间内每个元素加上一个值时,区间的和也加上这个值
 46 //        //对于区间求和, 原数组值需要加上lazy标记*子树所统计的区间长度
 47 //        a[i<<1]+=lazy[i]*(len-(len>>1));//(len-(len>>1)是左区间的长度
 48 //        a[i<<1|1]+=lazy[i]*(len>>1);//(len>>1)是右区间的长度
 49 //        lazy[i]=0;//由于懒惰标记向下传递,所以当前节点的懒惰标记取消
 50         lazy[i<<1]=lazy[i];
 51         lazy[i<<1|1]=lazy[i];
 52         a[i<<1]=lazy[i]*(len-(len>>1));
 53         a[i<<1|1]=lazy[i]*(len>>1);
 54         lazy[i]=0;
 55     }
 56     //对于区间求最大值, 子树的值不需要乘以长度, 所以不需要传递参数区间长度len。
 57 }
 58 
 59 //注意:
 60 // 1、单点更新, 不需要用到lazy标记
 61 // 2、成段(区间)更新, 需要用到lazy标记来提高时间效率
 62 void update(int x,int y,int L,int R,int i,int pluss)
 63 {
 64     if(L>=x&&R<=y)//当前节点区间包含在查询区间内
 65         //范围缩小到left和right之间
 66     {
 67 //        a[i]+=pluss*(R-L+1);
 68 //        lazy[i]+=pluss;
 69         a[i]=pluss*(R-L+1);
 70         lazy[i]=pluss;
 71         return;
 72     }
 73     pushdown(i,R-L+1);
 74     int mid=(L+R)>>1;
 75 
 76     //更新区间
 77     if(x<=mid)//更新左区间
 78         update(x,y,L,mid,i<<1,pluss);
 79     if(y>mid)//更新右区间
 80         update(x,y,mid+1,R,i<<1|1,pluss);
 81 
 82     //更新结点值
 83     a[i]=a[i<<1]+a[i<<1|1];
 84 }
 85 
 86 ll query(int x,int y,int L,int R,int i)//查询操作
 87 {
 88     if(L>=x&&R<=y)//当前节点区间包含在查询区间内
 89         return a[i];//返回当前值
 90     pushdown(i,R-L+1);
 91     int mid=(L+R)>>1;
 92     ll ans=0;
 93     if(x<=mid)//递归查询左子树内部的的区间值
 94         ans+=query(x,y,L,mid,i<<1);
 95     if(y>mid)//递归查询右子树内部的的区间值
 96         ans+=query(x,y,mid+1,R,i<<1|1);
 97     return ans;//返回题目所需的区间和(左+右)
 98 }
 99 
100 int main()
101 {
102     int n,q;
103     scanf("%d",&n);
104     build(1,n,1);
105     scanf("%d",&q);
106     for(int i=1;i<=q;i++)
107     {
108         int t,x,y;
109         scanf("%d %d %d",&t,&x,&y);
110         if(t==0)
111             printf("%lld\n",query(x,y,1,n,1));
112         else
113         {
114             int c;
115             scanf("%d",&c);
116             update(x,y,1,n,1,c);//修改为c,不是加上
117         }
118     }
119     return 0;
120 }
View Code

 

线段树区间修改(A->A+B)、查询

  1 //题意:
  2 //C:对区间[l,r]每一个数+c;
  3 // Q:查询区间[l,r]的所有元素的总和。
  4 
  5 //线段树修改和查找的时间复杂度都是O(logn)。
  6 //线段树基本思想:分治。
  7 //线段树基本操作:建树、区间查询(最值;和)、区间修改(更新)、单点修改、单点查询。
  8 
  9 #include
 10 #include<string.h>
 11 #include
 12 #include
 13 #include
 14 #include
 15 #include
 16 #include
 17 #include
 18 
 19 using namespace std;
 20 #define inf 0x3f3f3f3f;
 21 #define pi acos(-1.0)
 22 #define mem(a,b) memset(a,b,sizeof(a))
 23 #define eps 1e-9
 24 typedef long long ll;
 25 
 26 const int N=1e5+20;
 27 ll a[N<<2],lazy[N<<2];//需要开到节点的四倍大小
 28 
 29 void build(int L,int R,int i)
 30 {
 31     if(L==R)//当左右结点相同的时候,说明该节点可以建树,输入即可。
 32     {
 33         scanf("%lld",&a[i]);//即为叶子结点
 34         return;//因为已经确定这个点可以输入了,也就类似叶结点,返回函数上次调用的地方即可。
 35     }
 36 
 37     //否则往下继续找
 38     int mid=(L+R)>>1;
 39     build(L,mid,i<<1);//递归建立左子树
 40     build(mid+1,R,i<<1|1);//递归建立右子树
 41     a[i]=a[i<<1]+a[i<<1|1];//统计该点(i)的左子树和右子树之和
 42     //a这个操作也可以另外写到一个函数pushup中(即pushup(i)),这个看自己怎么写代码
 43     //节点数据向上更新
 44 
 45     //根据题意写,这一题是求区间和,之前左区间和右区间相加即可
 46     //例如如果求区间内最大值,则写成:a[i]=max(a[i<<1],a[i<<1|1]);
 47 }
 48 
 49 void pushdown(int i,int len)//节点懒惰标记下推
 50 {
 51     if(lazy[i])//如果懒惰标记为真,说明之前有过懒惰标记,现在需要进行更新
 52     {
 53         lazy[i<<1]+=lazy[i];//懒惰标记往左结点传
 54         lazy[i<<1|1]+=lazy[i];//懒惰标记往右结点传
 55         //左右用 |1 区分
 56         //因为求区间和,所以当区间内每个元素加上一个值时,区间的和也加上这个值
 57         //对于区间求和, 原数组值需要加上lazy标记*子树所统计的区间长度
 58         a[i<<1]+=lazy[i]*(len-(len>>1));//(len-(len>>1)是左区间的长度
 59         a[i<<1|1]+=lazy[i]*(len>>1);//(len>>1)是右区间的长度
 60         lazy[i]=0;//由于懒惰标记向下传递,所以当前节点的懒惰标记取消
 61     }
 62     //对于区间求最大值, 子树的值不需要乘以长度, 所以不需要传递参数区间长度len。
 63 }
 64 
 65 //注意:
 66 // 1、单点更新, 不需要用到lazy标记
 67 // 2、成段(区间)更新, 需要用到lazy标记来提高时间效率
 68 void update(int x,int y,int L,int R,int i,int pluss)
 69 {
 70     if(L>=x&&R<=y)//当前节点区间包含在查询区间内
 71         //范围缩小到left和right之间
 72     {
 73         a[i]+=pluss*(R-L+1);
 74         lazy[i]+=pluss;
 75         return;
 76     }
 77     pushdown(i,R-L+1);
 78     int mid=(L+R)>>1;
 79 
 80     //更新区间
 81     if(x<=mid)//更新左区间
 82         update(x,y,L,mid,i<<1,pluss);
 83     if(y>mid)//更新右区间
 84         update(x,y,mid+1,R,i<<1|1,pluss);
 85 
 86     //更新结点值
 87     a[i]=a[i<<1]+a[i<<1|1];
 88 }
 89 
 90 ll query(int x,int y,int L,int R,int i)//查询操作
 91 {
 92     if(L>=x&&R<=y)//当前节点区间包含在查询区间内
 93         return a[i];//返回当前值
 94     pushdown(i,R-L+1);
 95     int mid=(L+R)>>1;
 96     ll ans=0;
 97     if(x<=mid)//递归查询左子树内部的的区间值
 98         ans+=query(x,y,L,mid,i<<1);
 99     if(y>mid)//递归查询右子树内部的的区间值
100         ans+=query(x,y,mid+1,R,i<<1|1);
101     return ans;//返回题目所需的区间和(左+右)
102 }
103 
104 int main()
105 {
106     int n,q;
107     while(~scanf("%d %d",&n,&q))
108     {
109         mem(lazy,0);//如果多组数据lazy数组需要进行清空
110         mem(a,0);
111         build(1,n,1);//开始建树,传入树的总区间(传入最左端点,最右端点)和树的根节点
112         //建树的过程中输入每一个节点
113         for(int i=1;i<=q;i++)
114         {
115             char ch;
116             getchar();//吸收每次读入的空格
117             scanf("%c",&ch);
118             if(ch=='Q')//询问区间内的和
119             {
120                 int x,y;
121                 scanf("%d %d",&x,&y);
122                 ll ans=query(x,y,1,n,1);
123                 printf("%lld\n",ans);
124             }else if(ch=='C')//往区间内每一个数上都插入pluss
125             {
126                 int x,y,z;
127                 scanf("%d %d %d",&x,&y,&z);
128                 update(x,y,1,n,1,z);
129             }
130         }
131     }
132     return 0;
133 }
View Code

 

邻接表

 1 struct node
 2 {
 3     int v,flow,nextt;
 4 } e[M];
 5 
 6 int tot;
 7 
 8 void add(int u,int v,int flow)
 9 {
10     e[++tot].nextt=head[u];
11     head[u]=tot;
12     e[tot].v=v;
13     e[tot].flow=flow;
14 
15     e[++tot].nextt=head[v];
16     head[v]=tot;
17     e[tot].v=u;
18     e[tot].flow=0;
19 }
View Code

 

你可能感兴趣的:(ACM模板 - 持续更新中)