ACM模板

                                                                                     目录

搜索... 3

1.生日蛋糕... 3

2.迭代深搜。... 4

3.N皇后... 6

数论... 7

1.判断两个区间是否有交集... 7

2.大数因子打表... 8

3.矩阵快速幂... 8

4.  欧几里得算法... 10

5.  素数的判定(筛选法,miller_rabin算法,线性筛选). 11

6.  整除... 13

几何... 14

1.两直线相交问题... 14

2.求费马点... 16

3.给出经纬度求两点之间的距离... 17

动态规划... 18

1.最长公共子序列... 18

2.最长递增子序列... 19

3. 最长递增公共子序列... 19

7.  0-1背包... 20

8.  完全背包... 21

9.  多重背包... 21

10.  最长回文子序列... 22

线段树... 23

1.点修改... 23

2.  区间修改... 24

图论... 27

Dijkstra:... 27

SPFA:... 28

Bellman_Ford:... 29

Prim:. 30

Kruskal(求最小成树中的第K条最长边):... 31

技巧类... 33

1. 快速求一个数二进制1的个数(打表). 33

2.冒泡算法改进... 34

3.字典序最大子序列... 34

4.错排... 35

字符串... 37

1.Manacher算法(求最长回文子串)... 37

2.  求一个长度为N的字符串的子字符串不含有S的个数... 38

3.  字符串匹配(Kmp,Tire). 40

 

 

 

 

 

 

搜索

1.生日蛋糕:

给出体积NπM层,求出最小表面积。

#include

#include

int ans=0,N,M;

void dfs(int m,int V,int A,int R,int H)    ///剩下的层数,体积,表面积,当前最大半径,当前最大高度

{

   if(m*(R-1)*(R-1)*(H-1)

        return;

   if(V<0)   /// 剩下体积小于0

        return;

    if(A>ans&& ans)  //当前表面积 大于 当前最小表面积

        return;

    if(m==0)

    {

        if(V==0&& (A < ans || ans==0))    //更新最小表面积

           ans=A;

        return;

    }

    for(int r=R-1;r>=m; r--)  //最底层半径 最小为m

    {

        for(inth=H-1; h>=m; h--)  // 最底层高度 最小为m

        {

            intcV=r*r*h;

            intcA=2*r*h;

           if(m==M)

               cA+=r*r;

           if(A+2*V/r>ans && ans)  //当前表面积+剩余的侧面积>当前最小表面积

               continue;

           dfs(m-1,V-cV,A+cA,r,h);

        }

    }

}

int main()

{

   while(~scanf("%d %d",&N,&M))

    {

       dfs(M,N,0,100,100);   printf("%d\n",ans);

    }

    return 0;

}

2.迭代深搜。

Poj 1077 (8数码问题)

#include

#include

#include

using namespace std;

int a[10],flag=0,ans=0;

int goal[][2]={0,0,0,0,0,1,0,2,1,0,1,1,1,2,2,0,2,1,2,2};

int b[4][2]= {-1,0,0,-1,0,1,1,0};

int path[2000];

char op[5]="ulrd";

int nixushu()

{

    intsum=0;                    

    for (int i=0; i<9 ; i++)     

        if(a[i]!=9)

            for(int j=0 ; j

               if (a[j]!=9 && a[j]>a[i])

                   sum++ ;

    if (sum%2)

        return0;

    return 1;

}

int distance()

{

 

    int cost =0;

    int cc = 0;

    for(int i =0; i < 3; i++)

    {

        for(intj = 0; j < 3; j++)

        {

            cost+= abs(i-goal[a[cc]][0])+ abs(j-goal[a[cc]][1]);

           cc++;

        }

    }

    returncost;///理想距离  估算距离

}

void dfs(int cur,int len,int limit,int pre)

{

    intk=distance();

    if(k==0)

    {

        flag=1;

        ans=len;

        return;

    }

   if(len<=limit)

    {

        intx=cur/3;

        inty=cur%3;

        for(inti=0; i<4; i++)

        {

           if(len==0||(i+pre!=3))

            {

               int tx=x+b[i][0];

               int ty=y+b[i][1];

               if(tx<0||ty<0||tx>=3||ty>=3)

                   continue;

               swap(a[cur],a[tx*3+ty]);

               k=distance();

               if(len+k<=limit && flag==0)

               {

                   path[len]=i;

                   dfs(tx*3+ty,len+1,limit,i);

                   if(flag)

                       return;

               }

               swap(a[cur],a[tx*3+ty]);

            }

        }

    }

}

int main()

{

    char s[40];

    int t[10];

   while(gets(s))

    {

        intk=0,m;

       memset(t,0,sizeof(t));

       flag=0,ans=0;

        for(inti=0; s[i]; i++)

        {

           if(s[i]=='x')

               a[k++]=9;

            if(s[i]>='0'&&s[i]<='9')

               a[k++]=s[i]-'0';

        }

        for(inti=0; i<9; i++)

        {

           t[i]=a[i];

           if(a[i]==9)

               m=i;

        }

       if(nixushu())

        {

           flag=0;

            intlimit=0;

           while(flag==0)

            {

               for(int i=0; i<9; i++)

                   a[i]=t[i];

               dfs(m,0,limit,0);

               if(flag==0)

                   limit++;

            }

           for(int i=0; i

               printf("%c",op[path[i]]);

           printf("\n");

        }

        else

           printf("unsolvable\n");

    }

    return 0;

}

3.N皇后

#include

#include

int vis[3][50],s[20];

int n,sum;

void dfs(int h)

{

    int i;

    if(h==n+1)

    {

        sum++;

        return;

    }

    for(i=1;i<=n; i++)

    {

       if(vis[0][h-i+n]==0&&vis[1][i]==0&&vis[2][h+i]==0)

        {

           vis[0][h-i+n]=vis[1][i]=vis[2][h+i]=1;

           dfs(h+1);

           vis[0][h-i+n]=vis[1][i]=vis[2][h+i]=0;

        }

    }

}

int main()

{

    for(n=1;n<=10; n++)  //先打表,不然会超时

    {

       memset(vis,0,sizeof(vis));

        sum=0;

        dfs(1);

       s[n]=sum;

    }

   while(~scanf("%d",&n)&&n)

    {

       printf("%d\n",s[n]);

    }

    return 0;

}

数论

1.判断两个区间是否有交集

1.       正向思维:判断所有相交的情况

 

/**判断所有可能相交的情况

  * 1. A[1,5], B[4,8] A尾部与B首部相交(b1端必须在[a2,b2]之间)

  * 2. A[1,5], B[2,4] A包含B(B的两个端点都位于A中)

  * 3. A[2,5], B[1,3] A首部与B尾部相交(a1端必须在[a2,b2]之间)

  * 4. A[4,5], B[1,8] A被包含于B (a1,b1端必须都在[a2,b2]之间)

  **/

//因为A的一个端点落在B中name就有交集,所以第四点可省略

if((b1>a2&&b1b2) || (a1>a2&&a1

{return "有交集";} 

else

{return "无交集";}

2.       逆向思维:判断所有不相交的情况

/**判断所有可能相交的情况

  * 1. A[1,2], B[3,4] A位于B前面(b1小于a2)

  * 2. A[3,4], B[1,2] A位于B后面(a1大于b2)

  **/

if((a1< a2 && b1 < a2) || (b2 < a1 && a2 < a1))

{ return "无交集"}

else

{return "有交集"}

3.       优化逆向思维

 

/**

  *思路就是如果两个区间不相交,那么最大的开始端一定大于最小的结束端

  **/

if(max(a1,a2) < min(b1, b2))

{return "有交集"} 

else

{return "无交集"}

2.大数因子打表

memset(F,0,sizeof(F));

for(int i=1; i <=N/2 ; i++)

    for(intj=i+i; j<=N; j+=i)

        F[j]+=i;

3.矩阵快速幂

这是一个加强版的斐波那契数列。

给定递推式

求F(n)的值,由于这个值可能太大,请对109+7取模。

#include

#include

#define N 1000000007

struct note

{

    long longx[6][6];

};

 

note mul(note a,note b)

{

    note c= {0};

    for(int i=0;i<6; i++)

        for(intk=0; k<6; k++)

           for(int j=0; j<6; j++)

               c.x[i][j]=(c.x[i][j]+a.x[i][k]*b.x[k][j])%N;

    return c;

}

 

note pow(note a,long long n)

{

    note b= {0};

    for(int i=0;i<6; i++)

       b.x[i][i]=1;

    while(n)

    {

       if(n&1)

           b=mul(a,b);

       a=mul(a,a);

        n>>= 1;

    }

    return b;

}

 

int main()

{

    int t;

    long long n;

   scanf("%d",&t);

    while(t--)

    {

       scanf("%lld",&n);

       note a={0},b= {0};

        longlong ss[6][6] = {{1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0}, {0, 0, 1, 3, 3, 1},{0, 0, 0, 1, 2, 1}, {0, 0, 0, 0, 1, 1}, {0, 0, 0, 0, 0, 1}};

        b.x[0][0]=1,b.x[1][0]=0,b.x[2][0]=8,b.x[3][0]=4,b.x[4][0]=2,b.x[5][0]=1;

        for(inti=0; i<6; i++)

           for(int j=0; j<6; j++)

               a.x[i][j]=ss[i][j];

       printf("%lld\n",mul(pow(a,n),b).x[1][0]);

    }

    return 0;

}

4.    欧几里得算法

#include

#include

#include

#include

using namespace std;

__int64 gcd(__int64 y,__int64 x)

{

    __int64ans=0;

    if(x==0)

        ans=y;

    else

       ans=gcd(x,y%x);

    return ans;

}

int main()

{

    int t;

    __int64 A,B;

   scanf("%d",&t);

   scanf("%I64d %I64d",&A,&B);

    if(A>B)

       swap(A,B);

   printf("%I64d\n",gcd(A,B));

    return 0;

}

5.    素数的判定(筛选法,miller_rabin算法,线性筛选)

int get_prme()

{

    int k=0;

    for(int i=2;i<=1000000; i++)

    {

       if(!chick[i])

           a[k++]=i;

        for(intj=0; j

        {

           if(i*a[j]>1000000)

               break;

           chick[a[j]*i]=1;

           if(i%a[j]==0)

               break;

        }

    }

    return 0;

} //筛选法求素数

.线性筛选法——欧拉筛法

欧拉筛法通过红色标记部分保证每个合数只会被它的最小质因数筛去,时间复杂度降低到O(n)。

#include

#include

#define MAXN 100000

#define MAXL 1000000

int prime[MAXN];

_Bool check[MAXL];

 

int main()

{

    int n,count;

    while(~scanf("%d", &n))

    {

       memset(check, 0, sizeof(check));

        count =0;

        for (inti = 2; i <= n; i++)

        {

            if(!check[i])

               prime[count++] = i;

            for(int j = 0; j < count; j++)

            {

               if (i*prime[j] > MAXL)

                   break; // 过大的时候跳出

               check[i*prime[j]] = 1;

               if ((i%prime[j]) == 0) // 如果i是一个合数,而且i % prime[j] == 0

                   break;

            }

        }

        for (inti = 0; i < count; i++)

            printf("%d\n", prime[i]);

    }

    return 0;

}

miller_rabin算法

__int64 qpow(int a, int b, int r)

{

    __int64ans=1, buffer=a;

    while(b)

    {

       if(b&1) ans = ans*buffer%r;

        buffer =buffer*buffer%r;

       b>>=1;

    }

    return ans;

}

bool Miller_Rabbin(int n, int a)

{

    intr=0,s=n-1,j;

    if(!(n%a))

        returnfalse;

   while(!(s&1))

    {

       s>>=1;

        r++;

    }

    __int64k=qpow(a,s,n);

    if(k==1)

        returntrue;

   for(j=0;j

    {

       if(k==n-1)

               return true;       

    }

    returnfalse;

}

 

bool IsPrime(int n)

{

    inttab[]={2,3,5,7,11};

    for(inti=0;i<5;i++)

    {

       if(n==tab[i])

           return true;

       if(!Miller_Rabbin(n,tab[i]))

           return false;   

    }

    return true;

}

6.    整除

1.能被2整除的数:个位上为2的倍数
2. 能被4整除的数:个位和十位所组成的两位数能被4整除
3. 能被8整除的数:百位、个位、十位所组成的三位数能被8整除(注意顺序)
4. 能被5整除的数:个位上为5的倍数
5. 能被25整除的数:十位和个位所组成的两位数能被25整除
6. 能被125整除的数:百位、十位、个位所组成的数能被125整除
7. 能被3整除的数:各个数位上的数字和能被3整除
8. 能被9整除的数:各个数位上的数字和能被9整除
9. 能被11整除的数:奇数位(从左往右数)上的数字和与偶数位上的数字和的   差的绝对值能被11整除
10. 能被7整除的数:把个位数字截去,从余下的数中,减去个位数的2倍,如果差是7的倍数,则原数能被7整除,如果不好判断就递归处理
11. 能被13整除的数:把个位数字截去,从余下的数中,加上个位数的4倍,如果和是13的倍数,则原数能被13整除
12. 能被17整除的数:把个位数字截去,从余下的数中,加上个位数的5倍,如果和是17的倍数,则原数能被17整除,或把后三位截去,剩下的数与3倍后三位差的绝对值如果能被17整除,则原数能被17整除
13. 能被19整除的数:把个位数字截去,从余下的数中,加上个位数的2倍,如果和是19的倍数,则原数能被19整除,或把后三位截去,剩下的数与7倍后三位的差的绝对值如果能被19整除,则原数能被19整除

20.如果一个数能被99整除,这个数从后两位开始两位一截所得的所有数(如果有偶数位则拆出的数都有两个数字,如果是奇数位则拆出的数中若干个有两个数字还有一个是一位数)的和是99的倍数,这个数一定是99的倍数。

几何

1.两直线相交问题

#include

#include

 

long long int x[100001],y[100001];

int n,p=0;

 

int Find(int a,int b,int c)

{

    int ans=3;

    int d=0;

    for(int i=3;i<=n; i++)

    {

        if(i==p)

           continue;

       if((y[b]-y[a])*(x[i]-x[a])==(y[i]-y[a])*(x[b]-x[a]))

           ans++;

        else

        {

           if(d==0)

            {

               d=i;

               ans++;

            }

            elseif((y[d]-y[c])*(x[i]-x[c])==(y[i]-y[c])*(x[d]-x[c]))

               ans++;

        }

    }

    if(ans==n)

        return1;

    else

        return0;

}

int main()

{

   scanf("%d",&n);

 

    inta=1,b=2,c=0;

    for(int i=1;i<=n; i++)

       scanf("%lld %lld",&x[i],&y[i]);

    if(n<=4)

       printf("YES\n");

    else

    {

        for(inti=3; i<=n; i++)

           if((y[2]-y[1])*(x[i]-x[1])!=(y[i]-y[1])*(x[2]-x[1]))

            {

               c=i;

               p=i;

               break;

            }

        if(c==0)

            printf("YES\n");

        else

        {

            inti,j,k;

           i=Find(a,b,c);

           j=Find(a,c,b);

           k=Find(b,c,a);

           if(i==0&&j==0&&k==0)

               printf("NO\n");

            else

               printf("YES\n");

        }

    }

    return 0;

}

2.求费马点

#include

#include

#include

struct note

{

    double x,y;

};

double distance(note a,note b)

{

    returnsqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));

}

note F(note a,note b,note c)

{

    note u,v;

    doublestep=fabs(a.x)+fabs(a.y)+fabs(b.x)+fabs(b.y)+fabs(c.x)+fabs(c.y);

    int i,j,k;

   u.x=(a.x+b.x+c.x)/3;

   u.y=(a.y+b.y+c.y)/3;

   while(step>1e-10)

    {

        for(k=0;k<10; step/=2,k++)

           for(i=-1; i<=1; i++)

            {

               for(j=-1; j<=1; j++)

               {

                   v.x=u.x+step*i;

                   v.y=u.y+step*j;

                   if(distance(u,a)+distance(u,b)+distance(u,c)>distance(v,a)+distance(v,b)+distance(v,c))

                       u=v;

               }

            }

    }

    return u;

}

int main()

{

    notea,b,c,d;

   scanf("%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y);

    d=F(a,b,c);

   printf("%.6f %.6f\n",d.x,d.y);

    return 0;

}

3.给出经纬度求两点之间的距离

#include

#include

#include

using namespace std;

#define eps 1e-8

const double PI = 4*atan(1.0);

const double R = 6371009;

double xx1, yy1, zz1, xx2, yy2, zz2;

double weidu, jingdu;

double sqr(double x)

{

    return x*x;

}

int main()

{

    int T;

   cin>>T;

    while (T--)

    {

       scanf("%lf%lf",&weidu,&jingdu);

        weidu =weidu*PI/180;

        jingdu =jingdu*PI/180;

        xx1 =R*cos(weidu)*cos(jingdu); ///转成3维坐标

        yy1 =R*cos(weidu)*sin(jingdu);

        zz1 =R*sin(weidu);

       scanf("%lf%lf",&weidu,&jingdu);

        weidu =weidu*PI/180;

        jingdu =jingdu*PI/180;

        xx2 =R*cos(weidu)*cos(jingdu);

        yy2 =R*cos(weidu)*sin(jingdu);

        zz2 =R*sin(weidu);

        doubledist = sqrt(sqr(xx1-xx2)+sqr(yy1-yy2)+sqr(zz1-zz2));

        doubleang = acos((xx1*xx2+yy1*yy2+zz1*zz2)/(R*R));

        doubledist2 = ang*R;

       printf("%.0lf\n",dist2-dist+eps);

    }

    return 0;

}

动态规划

1.最长公共子序列

#include

#include

#include

using namespace std;

 

char s[1001],t[1001];

int dp[1001][1001];

 

int main()

{

   while(~scanf("%s %s",&s,&t))

    {

        intn=strlen(s);

        intm=strlen(t);

       memset(dp,0,sizeof(dp));

        for(inti=0; i

        {

           for(int j=0; j

            {

               if(s[i]==t[j])

               dp[i+1][j+1]=dp[i][j]+1;

               else

                   dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);

            }

        }

       printf("%d\n",dp[n][m]);

    }

    return 0;

}

2.最长递增子序列

#include

#include

#include

#define df 0x3f3f3f3f

using namespace std;

 

char s[1001];

int dp[1001];

 

int main()

{

   while(~scanf("%s",&s))

    {

        intn=strlen(s);

       memset(dp,df,sizeof(dp));

        for(inti=0; i

           *lower_bound(dp,dp+n,s[i])=s[i];

       printf("%d\n",lower_bound(dp,dp+n,df)-dp);

    }

    return 0;

}

3. 最长递增公共子序列

#include

#include

#include

using namespace std;

 

char a[505],b[505];

int dp[505],n,m;

 

int LICS()

{

    int i,j,MAX;

   memset(dp,0,sizeof(dp));

    for(i = 0;i

    {

        MAX = 0;

        for(j =0; j

        {

           if(a[i]>b[j] && MAX

                MAX = dp[j];

           if(a[i]==b[j])

               dp[j] = MAX+1;

        }

    }

    MAX = 0;

    for(i = 0;i

       if(MAX

            MAX= dp[i];

    return MAX;

}

int main()

{

   while(~scanf("%s%s",a,b))

    {

       n=strlen(a);

       m=strlen(b);

        int sum= LICS();

       printf("%d\n",sum);

    }

    return 0;

}

7.    0-1背包

#include

#include

#include

using namespace std;

 

int w[3600],v[3600];

int dp[13000];

int main()

{

    int n,m;

   while(~scanf("%d%d",&n,&m))

    {

       memset(dp,0,sizeof(dp));

        for(inti=0; i

           scanf("%d %d",&w[i],&v[i]);

        for(inti=0; i

           for(int j=m; j>=w[i]; j--)

               dp[j]=max(dp[j],dp[j-w[i]]+v[i]);

       printf("%d\n",dp[m]);

    }

    return 0;

}

8.    完全背包

#include

#include

#include

using namespace std;

 

int w[3600],v[3600];

int dp[13000];

int main()

{

    int n,m;

   while(~scanf("%d%d",&n,&m))

    {

       memset(dp,0,sizeof(dp));

        for(inti=0; i

           scanf("%d %d",&w[i],&v[i]);

        for(inti=0; i

           for(int j=w[i]; j<=m; j++)

               dp[j]=max(dp[j],dp[j-w[i]]+v[i]);

       printf("%d\n",dp[m]);

    }

    return 0;

}

9.    多重背包

#include

#include

#include

using namespace std;

 

int n,m;

int price[110],weight[110],counts[110];

int dp[110];

 

int main()

{

    int t;

   scanf("%d",&t);

    while(t--)

    {

       scanf("%d %d",&n,&m);

       memset(dp,0,sizeof(dp));

        for(inti=0; i

           scanf("%d %d %d",&price[i],&weight[i],&counts[i]);

           

        for(inti=0; i

           for(int k=1; k<=counts[i]; k++)

               for(int j=n; j>=price[i]; j--)

                   dp[j]=max(dp[j],dp[j-price[i]]+weight[i]);

                   

       printf("%d\n",dp[n]);

    }

    return 0;

}

10.  最长回文子序列

char s[2020];

int dp[2020][2020];

//dp[i][j]表示s[i~j]最长回文子序列

int LPS(char *s)

{

   memset(dp,0,sizeof(dp));

    int len =strlen(s);

    for(int i =len-1; i >= 0; --i)

    {

        dp[i][i]= 1;

        for(intj = i+1; j < len; ++j)

        {

           if(s[i] == s[j])    //头尾相同,最长回文子序列为去头尾的部分LPS加上头和尾

               dp[i][j] = dp[i+1][j-1] + 2;

           else    //头尾不同,最长回文子序列是去头部分的LPS和去尾部分LPS较长的

               dp[i][j] = max(dp[i][j-1],dp[i+1][j]);

        }

    }

    returndp[0][len-1]; }

线段树

1.    点修改

#include

#include

#include

using namespace std;

#define df 0x3f3f3f3f

 

struct note

{

    int maxm;

    int minn;

};

note ss[200003];

 

void build(int v,int l,int r)

{

    if(l==r)

    {

        int x;

       scanf("%d",&x);

       ss[v].maxm=x;

       ss[v].minn=x;

    }

    else

    {

        intmid=(l+r)/2;

       build(v*2,l,mid);

       build(v*2+1,mid+1,r);

       ss[v].maxm=max(ss[v*2].maxm,ss[2*v+1].maxm);

       ss[v].minn=min(ss[v*2].minn,ss[2*v+1].minn);

    }

}

note ask(int v,int l,int r,int ql,int qr)

{

    if(ql<=l&& r<=qr)

        returnss[v];

    intmid=(l+r)/2;

    note a,c,b;

   b.maxm=c.maxm=-df;

   b.minn=c.minn=df;

   if(qr<=mid)

       a=ask(v*2,l,mid,ql,qr);

    elseif(ql>mid)

       a=ask(v*2+1,mid+1,r,ql,qr);

    elseif(ql<=mid && mid<=qr)

    {

        b=ask(v*2,l,mid,ql,qr);

       c=ask(v*2+1,mid+1,r,ql,qr);

       a.maxm=max(b.maxm,c.maxm);

       a.minn=min(b.minn,c.minn);

    }

    return a;

}

int main()

{

    int n,m;

   while(~scanf("%d%d",&n,&m))

    {

        int x,y;

        notestr;

       build(1,1,n);

        for(inti=0; i

        {

           scanf("%d%d",&x,&y);

           str=ask(1,1,n,x,y);

           printf("%d\n",str.maxm-str.minn);

        }

    }

    return 0;

}

2.    区间修改

#include

#include

long long lazy[400002];

long long sum[400002]; //4*N

void build(long long v,long long l,long long r)

{

    if(l==r)

    {

        longlong x;

       scanf("%lld",&x);

       sum[v]=x;

    }

    else

    {

        longlong mid=(l+r)/2;

       build(v*2,l,mid);

       build(v*2+1,mid+1,r);

       sum[v]=sum[v*2]+sum[v*2+1];

    }

}

void pushdown(long long v,long long l,long long r)

{

   sum[v*2]+=lazy[v]*((r-l+2)/2);

   lazy[v*2]+=lazy[v];

   sum[v*2+1]+=lazy[v]*((r-l+1)/2);

    lazy[v*2+1]+=lazy[v];

    lazy[v]=0;

}

void update(long long v,long long l,long long r,longlong ql,long long qr,long long qn)

{

    if(ql<=l&& r<=qr)

    {

       sum[v]+=qn*(r-l+1);

       lazy[v]+=qn;

        return;

    }

    if(lazy[v])

       pushdown(v,l,r);

    long longmid=(l+r)/2;

   if(ql<=mid)

       update(v*2,l,mid,ql,qr,qn);

   if(qr>mid)

       update(v*2+1,mid+1,r,ql,qr,qn);

   sum[v]=sum[v*2]+sum[v*2+1];

}

long long ask(long long v,long long l,long long r,longlong ql,long long qr)

{

    long longnum=0;

    if(ql<=l&& r<=qr)

        returnsum[v];

    long longmid=(l+r)/2;

    if(lazy[v])

       pushdown(v,l,r);

   if(ql<=mid)

       num+=ask(v*2,l,mid,ql,qr);

   if(qr>mid)

       num+=ask(v*2+1,mid+1,r,ql,qr);

    return num;

}

int main()

{

    long longn,m;

   while(~scanf("%lld%lld",&n,&m))

    {

        char c;

        for(longlong i=0; i<=400001; i++)

           lazy[i]=0;

 

       build(1,1,n);

 

        for(longlong i=0; i

        {

            long long y,z,w;

           getchar();

           scanf("%c",&c);

           if(c=='C')

            {

               scanf("%lld%lld%lld",&y,&z,&w);

               update(1,1,n,y,z,w);

            }

           if(c=='Q')

            {

               scanf("%lld%lld",&y,&z);

               long long ans=ask(1,1,n,y,z);

               printf("%lld\n",ans);

            }

        }

    }

    return 0;

}

图论

Dijkstra:

#include

#define N 200

#define df 0x3f3f3f3f

using namespace std;

int dis[N],book[N],e[N][N];

int n,m,minn,u,v;

 

void init()

{

    for(int i=1;i<=n; i++)

        for(intj=1; j<=n; j++)

           if(i==j)

               e[i][j]=0;

            else

               e[i][j]=df;

}

void Dijkstra(int x)

{

   memset(book,0,sizeof(book));

    for(int i=1;i<=n; i++)

       dis[i]=e[x][i];

    book[x]=1;

    dis[x]=0;

    for(int i=1;i<=n-1; i++)

    {

        minn=df;

        for(intj=1; j<=n; j++)

        {

           if(book[j]==0 && dis[j]

            {

               u=j;

               minn=dis[j];

            }

        }

       book[u]=1;

        for(v=1;v<=n; v++)

        {

           if(e[u][v]dis[u]+e[u][v] &&book[v]==0)

               dis[v]=dis[u]+e[u][v];

        }

    }

}

 

int main()

{

    int x,y,z;

   scanf("%d %d",&n,&m);

    init();

    for(int i=0;i

    {

       scanf("%d%d%d",&x,&y,&z);

       e[x][y]=z;

    }

    Dijkstra(1);

    for(int i=1;i<=n; i++)

       printf("%d ",dis[i]);

   printf("\n");

    return 0;

}

SPFA:

void SPFA()

{

    for(int i =0; i < MAXN; i++)

        dis[i] =step[i] = INF, vis[i] = 0;

   queue Q;

    dis[0] =step[0] = 0, vis[0] = 1;

    Q.push(0);

   while(!Q.empty())

    {

        int u =Q.front();

        Q.pop();

        vis[u] =0;

        for(intj = 0; j < G[u].size(); j++)

        {

            intv = G[u][j].v;

           double len = G[u][j].dist;

           if(abs(dis[v]-dis[u]-len) <= EPS)

            {

                if(step[v] > step[u]+1)

                   step[v] = step[u]+1;

            }

            elseif(dis[v] >= dis[u]+len)

            {

               dis[v] = dis[u]+len;

               step[v] = step[u]+1;

               if(!vis[v])

               {

                   vis[v]=1;

                   Q.push(v);

               }

            }

        }

    }

}

Bellman_Ford:

#include

#define N 3100

#define df 0x3f3f3f3f

using namespace std;

int dis[N],u[N],v[N],w[N];

int First[N],next[N],book[N];

int n,m;

void Bellman_ford()

{

   queueQ;

    book[1]=1;

    Q.push(1);

   while(!Q.empty())

    {

        intk=First[Q.front()];

       while(k!=-1)

        {

           if(dis[u[k]]+w[k]

            {

               dis[v[k]]=dis[u[k]]+w[k];

               if(book[v[k]]==0)

               {

                   Q.push(v[k]);

                   book[v[k]]=1;

               }

            }

           k=next[k];

        }

       book[Q.front()]=0;

        Q.pop();

    }

}

int main()

{

 

   memset(book,0,sizeof(book));

scanf("%d%d",&n,&m);

    for(int i=1;i<=n; i++)

       First[i]=-1;

    for(int i=1;i<=n; i++)

       dis[i]=df;

    dis[1]=0;

    for(int i=1;i<=m; i++)

    {

       scanf("%d%d%d",&u[i],&v[i],&w[i]);

       next[i]=First[u[i]];

       First[u[i]]=i;

    }

   Bellman_ford();

    for(int i=1;i<=n; i++)

       printf("%d ",dis[i]);

    return 0;

}

Prim:

#include

#include

#define df 0x3f3f3f3f

int e[110][110],dis[110],book[110];

int n,minn,u;

void prim()

{

    intnum=0,sum=0;

   memset(book,0,sizeof(book));

    for(int i=1;i<=n; i++)

        dis[i]=e[1][i];

    book[1]=1;

    num++;

   while(num

    {

        minn=df;

        for(inti=1; i<=n; i++)

        {

           if(book[i]==0 && dis[i]

            {

               minn=dis[i];

               u=i;

            }

        }

       book[u]=1;

        num++;

       sum+=dis[u];

        for(intk=1; k<=n; k++)

        {

           if(book[k]==0&&dis[k]>e[u][k])

               dis[k]=e[u][k];

        }

    }

   printf("%d\n",sum);

}

int main()

{

   while(~scanf("%d",&n))

    {

       memset(e,df,sizeof(df));

        for(inti=1; i<=n; i++)

           for(int j=1; j<=n; j++)

               scanf("%d",&e[i][j]);

        prim();

    }

    return 0;

}  

Kruskal(求最小成树中的第K条最长边):

#include

#include

#include

#include

using namespace std;

 

int f[550],x[550],y[550];

int dis[360000];

struct note

{

    int u,v,w;

} s[360000];

 

 

int Find(int x)

{

    if(f[x]==x)

        returnx;

    else

        returnf[x]=Find(f[x]);

}

int merge(int x,int y)

{

    intt1=Find(x);

    intt2=Find(y);

    if(t1!=t2)

    {

       f[t1]=t2;

        return1;

    }

    return 0;

}

bool cmp(note a,note b)

{

    returna.w

}

 

bool cmp1(int x1,int y1)

{

    returnx1>y1;

}

 

int diss(int a1,int b1)

{

    intmm=(x[a1]-x[b1])*(x[a1]-x[b1])+(y[a1]-(y[b1]))*(y[a1]-y[b1]);

    return mm;

}

 

int main()

{

    int n,m,t;

   scanf("%d",&t);

    while(t--)

    {

       scanf("%d%d",&n,&m);

        intnum=0,k=0;

        for(inti=1; i<=m; i++)

           scanf("%d%d",&x[i],&y[i]);

        for(inti=1; i<=m; i++)

        {

           for(int j=i+1; j<=m; j++)

            {

               s[k].u=i;

               s[k].v=j;

               s[k++].w=diss(i,j);

            }

        }

       sort(s,s+k,cmp);

        for(inti=1; i<=m; i++)

           f[i]=i;

        for(inti=0; i

        {

           if(merge(s[i].u,s[i].v))

            {

               dis[num++]=s[i].w;

            }

           if(num==m-1)

               break;

        }

       sort(dis,dis+num,cmp1);

       printf("%.2f\n",sqrt(dis[n-1]*1.0));

       //printf("%.2f\n",sqrt(dis[n-1]*1.0));

    }

    return 0;

}

技巧类

1. 快速求一个数二进制1的个数(打表)

void init()

{

    int sum=0;

    f[0]=0;

    f[1]=1;

    f[2]=1;

    f[3]=2;

    for(int i=4;i<=1000000; i++)

    {

        sum=0;

        int y=i;

        while(y)

        {

           sum++;  //只要n不为0则其至少有一个1

            y =y & (y - 1);

        }

       f[i]=sum;

    }

}

2.冒泡算法改进

void booblesort(int a[], int n)

{

    bool sorted = false;

    while (!sorted)

    {

        sorted= true;

        for(int i = 1; i <= n - 1; i++)

        {

            if(a[i] > a[i + k]&&i+k<=n)

            {

                swap(a[i],a[i + k]);

                sorted= false;

            }

        }

        n--;

    }

}

3.字典序最大子序列

#include

#include

#include

using namespace std;

char a[100001];

int main()

{

   while(~scanf("%s",a))

    {

        strings;

        intmaxm1=-0x3f3f3f3f,maxm2=-0x3f3f3f3f;

        intn=strlen(a),pos;

        for(inti=0; i

        {

            if(a[i]-'a'>maxm1)

            {

               maxm1=a[i]-'a';

               pos=i;

            }

        }

        for(inti=n-1;i>=pos; i--)

        {

           if(a[i]-'a'>=maxm2)

            {

               s+=a[i];

               maxm2=a[i]-'a';

            }

 

        }

        for(inti=s.size()-1; i>=0; i--)

           cout<

       cout<

    }

    return 0;

 

}

4.错排

#include

#include

#include

using namespace std;

typedef long long ll;

#define mod 1000000007

ll F[100110],A[10110];

void init()

{

    A[0]=1;

    A[1]=0;

    A[2]=1;

    F[1]=1;

    F[2]=2;

    for(ll i=3;i<=10001; i++)

    {

       A[i]=((i-1)*A[i-1]%mod+(i-1)*A[i-2]%mod)%mod;

       F[i]=(F[i-1]*i)%mod;

    }

}

ll pow(ll x,ll n)

{

    ll res=1;

    while(n)

    {

       if(n&1)

           res=res*x%mod;

       n>>=1;

       x=x*x%mod;

    }

    return res;

}

ll C(ll n,ll m)

{

    if(m > n)

        return0;

   if(m==0)  /// 全部对应相同

        return1;

    if(m>n-m)

        m=n-m;

    ll sum=1;

    ll sum1=1;

    ll k=n;

    for(ll i=1;i<=m; i++) /// n*(n-1)*(n-2)*******(n-m+1)

    {

       sum=sum*k%mod;

        k--;

       sum1=sum1*i%mod;

    }

    returnsum*pow(sum1,mod-2)%mod;

}

int main()

{

    int t;

    ll n,k;

    init();

   scanf("%d",&t);

    while(t--)

    {

        llsum=0;

       scanf("%lld%lld",&n,&k);

        for(lli=0; i

           sum=(sum+C(n,i)*A[n-i]%mod)%mod;

       printf("%lld\n",(F[n]-sum+mod)%mod);

    }

    return 0;

}

字符串

1.     Manacher算法(求最长回文子串)

#include

#include

using namespace std;

string s;

int p[110050*2];   //  这里需要注意,数组的长度大于字符串的长度的两倍;

//  将字符串转换成奇字符串

void init()

{

   memset(p,0,sizeof(p));

    strings1="$";

    for(int i=0;i

    {

        s1+='#';

       s1+=s[i];

    }

    s1+='#';

    s=s1;

}

//  计算p[id]表示id位置的回文半径

void Manacher()

{

    intid=0;       //  id位置的右边界最靠右(在已知范围内);

    intmx=0;       //  id的右边界位置;

    for(int i=1;i

    {

        if(mx>i)

           p[i]=min(p[2*id-i],mx-i);

        else

           p[i]=1;

        for(;s[i-p[i]]==s[i+p[i]]; p[i]++);

       if(i+p[i]>mx)

        {

           mx=i+p[i];

           id=i;

        }

    }

}

int main()

{

   cin.sync_with_stdio(false);

   while(cin>>s)

    {

        init();

       Manacher();

        intans=0;

        for(inti=1; i

        {

           if(ans

               ans=p[i];

        }

       cout<

    }

    return 0;

}

2.     求一个长度为N的字符串的子字符串不含有S的个数

#include

#include

using namespace std;

 

const char *AGCT="AGCT";

const int MOD = 10009;

int next[200][4];

int dp[10000][110];

int N,K;

string S;

 

void solve()

{

 

    for(int i=0;i

    {

 

        for(intj=0; j<4; j++)

        {

           //printf("***\n");

            /// 在S长度为i的前缀添加一个字符

           string s=S.substr(0,i)+AGCT[j];

            ///反复删除第一字符,直到成为S的前缀

           while(S.substr(0,s.length())!=s)

               s=s.substr(1);

           next[i][j]=s.length();

        }

    }

}

int main()

{

   scanf("%d%d",&N,&K);

   cin>>S;

    solve();

   memset(dp,0,sizeof(dp));

    dp[0][0]=1;

    for(int t=0;t

    {

        for(inti=0; i

        {

           for(int j=0; j<4; j++)

            {

               int ti=next[i][j];

               if(ti==K)

                   continue;

               dp[t+1][ti]=(dp[t+1][ti]+dp[t][i])%MOD;

            }

        }

    }

    int ans=0;

    for(int i=0;i

       ans=(ans+dp[N][i])%MOD;

   printf("%d\n",ans);

    return 0;

}

3.    字符串匹配(Kmp,Tire)

Kmp:

#include

#include

#include

#define MAXN 100

using namespace std;

 

int next[MAXN];

 

void getnext(char *s)

{

    inti=-1,j=0,len=strlen(s);

    next[0]=-1;

   while(j

       if(i==-1||s[i]==s[j])

        {

            i++;

            j++;

           next[j]=i;

        }

        else

           i=next[i];

}

 

bool kmp(char *s0,char *s1)

{

    inti=0,j=0,len0=strlen(s0),len1=strlen(s1);

   while(i

       if(i==-1||s0[i]==s1[j])

           i++,j++;

        else

           j=next[j];

    returni==len1;

}

 

int kmp_len(char *s0,char *s1)

{

    inti=0,j=0,maxlen=0,len0=strlen(s0),len1=strlen(s1);

   while(i

       if(i==-1||s0[i]==s1[j])

           maxlen=max(++i,maxlen),j++;

        else

           j=next[j];

    returnmaxlen;

}

 

int main()

{

    chars0[MAXN],s1[MAXN];

   while(scanf("%s%s",s0,s1)!=EOF)

    {

       getnext(s1);

       puts(kmp(s0,s1)?"YES":"NO");

       printf("%d\n",kmp_len(s0,s1));

    }

    return 0;

}

Tire:

#include

#include

#include

#include

using namespace std;

typedef unsigned long long ull;

const ull B =100000007;

 

string a,b,c;

 

bool check(string a,string b)

{

    inta1=a.length(),b1=b.length();

    if(a1

    ull t=1;

    for(int i=0;i

    ullah=0,bh=0;

    for(int i=0;i

    for(int i=0;i

    for(int i=0;i+b1<=a1; i++)

    {

       if(ah==bh) return true;

       if(i+b1

    }

    returnfalse;

}

 

int main()

{

   ios_base::sync_with_stdio(false);

    int t;

   cin>>t;

    while(t--)

    {

       cin>>a>>b;

        for(inti=a.length()-1; i>=0; i--)

           if(a[i]=='0') a.erase(i);

            elsebreak;

        for(inti=b.length()-1; i>=0; i--)

           if(b[i]=='0') b.erase(i);

            elsebreak;

        int l=b.length(),flag=0;

       c="";

        for(inti=l-1; i>=0; i--)

           c+=b[i];

       if(check(a,b))

           flag=1;

        elseif(check(a,c)) flag=1;

        if(flag)

           cout<<"Alice"<

        elsecout<<"Bob"<

    }

    return 0;

}

 

你可能感兴趣的:(ACM模板)