zoukankan      html  css  js  c++  java
  • C++模板

    (考前复习)

    一、图论

    1、最小生成树

    (1)Kruskal

     1 #include <algorithm>
     2 #include <cstdio>
     3 #define ll long long
     4 struct node{
     5     int u,v,w;
     6 }g[200005];
     7 int cnt,fa[100005],num,n,m;
     8 void add(int x,int y,int z)
     9 {
    10     g[++num].u=x;  g[num].v=y;  g[num].w=z;
    11     return;
    12 }
    13 bool cmp(node x,node y)
    14 {
    15     return x.w<y.w;
    16 }
    17 int find(int x)
    18 {
    19     if (x==fa[x]) return x;
    20     return fa[x]=find(fa[x]);
    21 }
    22 ll Kruskal()
    23 {
    24     if (n==1) return 0;
    25     int i,cnt=0,fu,fv;
    26     ll tot=0;//  最小生成树权值和
    27     std::sort(g+1,g+m+1,cmp);
    28     for (i=1;i<=n;i++) fa[i]=i;
    29     for (i=1;i<=m;i++)
    30     {
    31         fu=find(g[i].u);
    32         fv=find(g[i].v);
    33         if (fu==fv) continue;
    34         fa[fv]=fu;
    35         tot+=g[i].w;
    36         cnt++;
    37         if (cnt==n-1) return tot;
    38     }
    39 }
    40 int main()
    41 {
    42     int i,j,x,y,z;
    43     scanf("%d%d",&n,&m);   //  n个 顶点,m 条边
    44     for (i=1;i<=m;i++)
    45       scanf("%d%d%d",&x,&y,&z),
    46       add(x,y,z);  //  x 和 y 有一条权值为 z 的边
    47     printf("%lld",Kruskal());
    48     return 0;
    49 }
    View Code

    (2)Prim

    1 #include <algorithm>
     2 #include <cstring>
     3 #include <cstdio>
     4 #define ll long long
     5 struct node{
     6     int u,w,nex;
     7 }g[200005];
     8 int num,n,m,fir[100005]; 
     9 bool vis[100005];
    10 ll dis[100005];  
    11 void add(int x,int y,int z)
    12 {
    13     g[++num].u=y;  g[num].w=z;  g[num].nex=fir[x];  fir[x]=num;
    14     return;
    15 }
    16 ll Prim()
    17 {
    18     int i,j,k,p,cnt=0;
    19     ll tot=0,minv;  //  最小生成树权值和 
    20     memset(dis,127,sizeof(dis));
    21     dis[1]=0; 
    22     while (cnt<n)
    23     {
    24         for (p=-1,minv=3e9,j=1;j<=n;j++)
    25           if (!vis[j] && dis[j]<minv)
    26             minv=dis[j],p=j;
    27         tot+=dis[p];  vis[p]=1;  cnt++;
    28         for (k=fir[p];k;k=g[k].nex)
    29           if (!vis[g[k].u] && dis[g[k].u]>g[k].w) 
    30             dis[g[k].u]=g[k].w;
    31     } 
    32     return tot;
    33 }
    34 int main()
    35 {
    36     int i,j,x,y,z;
    37     scanf("%d%d",&n,&m);  // n 个顶点,m 条边 
    38     for (i=1;i<=m;i++)
    39       scanf("%d%d%d",&x,&y,&z),
    40       add(x,y,z),add(y,x,z);  // x 和 y 之间有一条权值为 z 的边 
    41     printf("%lld",Prim());
    42     return 0;
    43 }
    View Code

    2、最短路

    (1)SPFA

     1 #include <algorithm>
     2 #include <cstring>
     3 #include <cstdio>
     4 #define ll long long
     5 const int maxn=10005;
     6 struct node{
     7     int u,w,nex;
     8 }g[500005];
     9 int num,n,m,fir[10005],s,q[10005],h,t; 
    10 bool vis[10005];
    11 ll dis[10005];  
    12 void add(int x,int y,int z)
    13 {
    14     g[++num].u=y;  g[num].w=z;  g[num].nex=fir[x];  fir[x]=num;
    15     return;
    16 }
    17 void spfa()
    18 {
    19     int i,j,k,u,v;
    20     for (i=1;i<=n;i++) dis[i]=2147483647;
    21     dis[s]=0; h=0; t=1; q[1]=s; vis[s]=1;
    22     while (h!=t)
    23     {
    24         (++h)%=maxn; u=q[h]; vis[u]=0;  
    25         for (k=fir[u];k;k=g[k].nex)
    26         {
    27             v=g[k].u;
    28             if (dis[u]+g[k].w<dis[v]) 
    29             {
    30                 dis[v]=dis[u]+g[k].w;
    31                 if (!vis[v])
    32                 {
    33                     vis[v]=1;
    34                     (++t)%=maxn;
    35                     q[t]=v;
    36                 }
    37             }
    38         }
    39     }
    40     return;
    41 } 
    42 int main()
    43 {
    44     int i,j,x,y,z;
    45     scanf("%d%d%d",&n,&m,&s);  // n 个顶点,m 条边,起点 s 
    46     for (i=1;i<=m;i++)
    47       scanf("%d%d%d",&x,&y,&z),
    48       add(x,y,z);  // 一条从 x 指向 y 的边权值为 z 
    49     spfa();
    50     for (i=1;i<=n;i++) printf("%d ",dis[i]);
    51     return 0;
    52 }
    View Code

    (2)SPFA双端队列优化

     1 #include <cstring>
     2 #include <cstdio>
     3 const int maxn=20005;
     4 struct node{
     5     int u,w,nex;
     6 }g[100005];
     7 int n,m,fir[10005],num,q[20005],dis[10005];
     8 bool vis[10005];
     9 void add(int x,int y,int z)
    10 {
    11     g[++num].u=y;  g[num].w=z;  g[num].nex=fir[x];  fir[x]=num;
    12     return;
    13 }
    14 void spfa(int S)
    15 {
    16     int u,v,i,h,t;
    17     memset(dis,63,sizeof(dis));
    18     memset(vis,0,sizeof(vis));
    19     dis[S]=0;    
    20     h=0;  t=1;  q[1]=S;  vis[S]=1;
    21     while (h!=t)
    22     {
    23         (++h)%=maxn;
    24         u=q[h];  vis[u]=0;
    25         for (i=fir[u];i;i=g[i].nex)
    26         {
    27             v=g[i].u;
    28             if (dis[v]>dis[u]+g[i].w)
    29             {
    30                 dis[v]=dis[u]+g[i].w;
    31                 if (!vis[v])
    32                 {
    33                     vis[v]=1;
    34                     if (dis[v]<dis[q[(h+1)%maxn]])
    35                       q[h]=v,h=(h-1+maxn)%maxn;
    36                     else (++t)%=maxn,q[t]=v;
    37                 }
    38             }
    39         }
    40     }
    41     return;
    42 }
    43 int main()
    44 {
    45     int i,j,t,p,x,y,z;
    46     scanf("%d%d",&n,&m);
    47     for (i=1;i<=m;i++)
    48       scanf("%d%d%d",&x,&y,&z),
    49       add(x,y,z),add(y,x,z);
    50     spfa(1);    
    51     return 0;
    52 }
    View Code

    (3)Dijkstra优先队列优化

    1 #include <cstdio>
     2 #include <vector>
     3 #include <queue>
     4 #define ll long long
     5 #define pa pair<ll,int>
     6 using namespace std;
     7 struct node{
     8     int u,w,nex;
     9 }g[1000005];
    10 int n,m,fir[500005],num;
    11 ll dis[500005];
    12 priority_queue <pa,vector<pa>,greater<pa> > q;
    13 void add(int x,int y,int z)
    14 {
    15     g[++num].u=y;  g[num].w=z;  g[num].nex=fir[x];  fir[x]=num;
    16     return;
    17 }
    18 void dijkstra(int S)
    19 {
    20     int h=0,t=1,u,v,i;
    21     for (i=1;i<=n;i++) dis[i]=1e15;
    22     dis[S]=0;
    23     q.push(make_pair(0,S));
    24     while (!q.empty())
    25     {
    26         u=q.top().second;  q.pop();
    27         for (i=fir[u];i;i=g[i].nex)
    28         {
    29             v=g[i].u;
    30             if (dis[v]>dis[u]+g[i].w)
    31               dis[v]=dis[u]+g[i].w,
    32               q.push(make_pair(dis[v],v));     
    33         }
    34     }
    35     return;
    36 }
    37 int main()
    38 {
    39     int i,j,x,y,z,p;
    40     scanf("%d%d",&n,&m);
    41     for (i=1;i<=m;i++)
    42       scanf("%d%d%d",&x,&y,&z),
    43       add(x,y,z),add(y,x,z);
    44     dijkstra(1); 
    45     return 0;
    46 }
    View Code

    (4)Dijkstra手打堆优化

     1 #include <cstring>
     2 #include <cstdio>
     3 struct node{
     4     int u,w,nex;
     5 }g[400005];
     6 struct note{
     7     int dis,id;
     8 }h[100005];
     9 int n,m,fir[100005],d[100005],num;
    10 int pos[100005],siz;
    11 void add(int x,int y,int z) 
    12 {
    13     g[++num].u=y;  g[num].w=z;  g[num].nex=fir[x];  fir[x]=num;
    14     return;
    15 }
    16 void put(int x)
    17 {
    18     int fa;
    19     note t;
    20     while (x>1)
    21     {
    22         fa=x>>1;
    23         if (h[x].dis>=h[fa].dis) break;
    24         pos[h[x].id]=fa;  pos[h[fa].id]=x;
    25         t=h[x];  h[x]=h[fa];  h[fa]=t;
    26         x=fa;
    27     }
    28     return;
    29 }
    30 void get(int x)
    31 {
    32     int son;
    33     note t;
    34     h[1]=h[siz--];
    35     while (x*2<=siz)
    36     {
    37         son=x<<1;
    38         if (son<siz && h[son].dis>h[son+1].dis) son++;
    39         if (h[x].dis<=h[son].dis) break;
    40         pos[h[x].id]=son;  pos[h[son].id]=x;
    41         t=h[x];  h[x]=h[son];  h[son]=t;
    42         x=son;
    43     }
    44     return ;
    45 }
    46 void dijkstra()
    47 {
    48     int i,j,u,v,p;
    49     note top;
    50     for (i=1;i<=n;i++)
    51       h[++siz].dis=d[i],h[siz].id=i,pos[i]=siz;
    52     for (i=1;i<=n;i++)
    53     {
    54         top=h[1];  get(1);  pos[top.id]=0;
    55         for (j=fir[top.id];j;j=g[j].nex)
    56         {
    57             v=g[j].u;
    58             if (pos[v]>0 && top.dis+g[j].w<h[pos[v]].dis)
    59               p=pos[v],
    60               h[p].dis=top.dis+g[j].w,
    61               d[v]=h[p].dis,
    62               put(p);
    63         }    
    64     }  
    65     return;
    66 }
    67 int main() 
    68 {
    69     int i,j,k,x,y,z;
    70     memset(fir,0,sizeof(fir));
    71     memset(d,63,sizeof(d));
    72     scanf("%d%d",&n,&m);
    73     d[1]=num=siz=0;
    74     for (i=1;i<=m;i++)
    75       scanf("%d%d%d",&x,&y,&z),
    76       add(x,y,z);
    77     dijkstra();
    78     for (i=1;i<=n;i++)
    79       printf("%d ",d[i]);
    80     return 0;
    81 }
    View Code

    (5)Floyd

     1 #include<cstdio>
     2 const int inf=1e9;
     3 int m,n; 
     4 int map[505][505],b[505],path[505][505];  //path[i][j]记录路径
     5 void floyd()
     6 {
     7     int i,j,k;
     8     for(k=1;k<=n;k++)
     9       for(i=1;i<=n;i++)
    10         for(j=1;j<=n;j++)
    11           if(map[i][j]>map[i][k]+map[k][j])
    12             map[i][j]=map[i][k]+map[k][j], 
    13             path[i][j]=path[i][k];
    14     return;
    15 }
    16 int main()
    17 {
    18     int i,j,u,v,len;
    19     scanf("%d%d",&n,&m); //输入城市数量 和 道路数量
    20     //初始化
    21     for(i=1;i<=n;i++)
    22       for(j=1;j<=n;j++)
    23         map[i][j]=inf,
    24         path[i][j]=j;   
    25     while(m--)
    26       scanf("%d%d%d",&u,&v,&len),
    27       map[u][v]=map[v][u]=len;
    28     floyd();//进行每对节点的求最小路径
    29     while(scanf("%d%d",&u,&v))
    30     {//输入起点和终点
    31         int tmp=u;
    32         printf("%d",u);
    33         while(tmp!=v)//打印路径
    34           printf("-->%d",path[tmp][v]),
    35           tmp=path[tmp][v];
    36         //输出最小花费
    37         printf("
    ");
    38         printf("cost: %d",map[u][v]);
    39     }
    40     return 0;
    41 }
    View Code

    3、强连通分量

    (1)Kosaraju

    1 #include <cstdio>
     2 struct note{
     3     int u,nex;
     4 };
     5 note g[40005],gp[40005];
     6 int fir[205],firp[205],s,t,q[205],m,n;
     7 int mark[205];   // 点u属于哪个连通块 
     8 bool vis[205];
     9 void ADD(int k,int x,int y)
    10 {
    11     g[k].u=y;   g[k].nex=fir[x];   fir[x]=k;
    12     gp[k].u=x;  gp[k].nex=firp[y]; firp[y]=k; 
    13 }
    14 void dfs1(int u)
    15 {
    16     vis[u]=true;
    17     for (int k=fir[u];k;k=g[k].nex)
    18       if (!vis[g[k].u])
    19         dfs1(g[k].u);
    20     q[++t]=u;
    21     return ;    
    22 }
    23 void dfs2(int u,int t)
    24 {
    25     vis[u]=true;
    26     mark[u]=t;
    27     for (int k=firp[u];k;k=gp[k].nex)
    28       if (!vis[gp[k].u])
    29         dfs2(gp[k].u,t);
    30     return;    
    31 }
    32 void scc()
    33 {
    34     int i;
    35     for (i=1;i<=n;i++)
    36       if (!vis[i])
    37         dfs1(i);
    38     for (i=0;i<=n;i++)
    39       vis[i]=false;
    40     for (i=n;i>=1;i--)
    41       if (!vis[q[i]])
    42         dfs2(q[i],++s);
    43     return;          
    44 }
    45 int main()
    46 {
    47     int i,j,k,x,y;
    48     scanf("%d%d",&n,&m);
    49     for (i=1;i<=m;i++)
    50       scanf("%d%d",&x,&y),
    51       ADD(++t,x,y);
    52     t=0;
    53     scc();
    54     printf("%d",s);  //  输出强连通分量个数 
    55     return 0;
    56 }
    View Code

    (2)tarjan

    1 #include <cstdio>
     2 struct note{
     3     int x,nex;
     4 };
     5 note g[8005];
     6 int fir[3005],stack[3005],dfn[3005],low[3005],zone[3005],ind[3005];
     7 int m,n,a,b,s,t,p,num;
     8 long long mark[3005];
     9 bool vis[3005];   //  标记结点是否在栈里 
    10 void ADD(int k,int x,int y)
    11 {
    12     g[k].x=y;   g[k].nex=fir[x];   fir[x]=k;
    13 }
    14 void tarjan(int u)
    15 {
    16     stack[++t]=u;
    17     vis[u]=true;
    18     low[u]=dfn[u]=++s;
    19     for (int k=fir[u];k;k=g[k].nex)
    20     {
    21         int v=g[k].x;
    22         if (!dfn[v])
    23         {
    24             tarjan(v);
    25             if (low[v]<low[u])
    26               low[u]=low[v];
    27         }
    28         else
    29           if (vis[v] && dfn[v]<low[u])
    30             low[u]=dfn[v];
    31     }
    32     if (low[u]==dfn[u])   //  找到一个强连通分量 
    33     {
    34         num++;  int v,tt=t;
    35         do
    36         {
    37             v=stack[t];
    38             vis[v]=false;
    39             zone[v]=num;   //  标记结点所属强连通分量
    40             t--;
    41         }while (u!=v);
    42     }
    43     return;
    44 }
    45 int main()
    46 {
    47     int i,j,k;
    48     long long x;
    49     scanf("%d",&n);  
    50     scanf("%d",&m);
    51     for (i=1;i<=m;i++)
    52     {
    53         scanf("%d%d",&a,&b);
    54         ADD(++t,a,b);
    55     }
    56     t=0;  
    57     for (i=1;i<=n;i++)
    58       if (!dfn[i])
    59         tarjan(i);
    60     for (i=1;i<=n;i++)           // 缩点 
    61       for (k=fir[i];k;k=g[k].nex)      
    62       {
    63             int v=g[k].x;
    64             if (zone[i]!=zone[v])
    65                ind[zone[v]]++; 
    66       }
    67     return 0;
    68 }
     
    View Code

    4、割点与桥

     1 void tarjan(int u,int fa)  
     2 {  
     3     int cnt=0;  
     4     low[u]=dfn[u]=++idx;  
     5     for(int i=0;i<(int)adj[u].size();i++)  
     6     {  
     7         int v=adj[u][i];  
     8         if(v==fa) continue;  
     9         if(!dfn[v])   
    10         {  
    11             tarjan(v,u);  
    12             ++cnt;  
    13             low[u]=min(low[u],low[v]);  
    14             if( (root==u&&cnt>1)||(root!=u&&dfn[u]<=low[v]) ) //判断是否是割点  
    15                 isap[u]=1;  
    16             if(dfn[u]<low[v]) cutE[++numE]=Edge(u,v);//判断是否是桥,视具体情况采用恰当的结构记录。  
    17         }  
    18         else low[u]=min(low[u],dfn[v]);//这里不用判断是否点v在栈中  
    19     }  
    20 }  
    View Code

     
    5、点双连通分量

      1 /*无向图的双连通分量:
      2 
      3 割顶的bccno无意义:割点的bccno会被多次赋值,所以//它的值无意义。
      4 
      5 调用结束后, S保证为空:
      6 对于点双连通分支,实际上在求割点的过程中就能顺便把每个点双连通分支求出。
      7 建立一个栈,存储当前双连通分支,在搜索图时,每找到一条树枝边或后向边(非横叉边),
      8 就把这条边加入栈中。如果遇到某时满足DFS(u)<=Low(v),说明u是一个割点,
      9 同时把边从栈顶一个个取出,直到遇到了边(u,v),取出的这些边与其关联的点,
     10 组成一个点双连通分支。割点可以属于多个点双连通分支,其余点和每条边只属于且
     11 属于一个点双连通分支。*/
     12  
     13 #include <iostream>
     14 #include <cstdlib>
     15 #include <cstdio>
     16 #include <algorithm>
     17 #include <cstring>
     18 #include <stack>
     19 #include <vector>
     20 #include <queue>
     21 #include <map>
     22 
     23 using namespace std;
     24 
     25 const int maxn = 6;
     26 
     27 int pre[maxn], iscut[maxn], bccno[maxn], low[maxn],dfs_clock, bcc_cnt;
     28 vector<int> G[maxn], bcc[maxn];
     29 
     30 struct Edge{
     31     int u, v;
     32 };
     33 stack<Edge> S;
     34 int dfs(int u, int fa){
     35     int lowu = pre[u] = ++dfs_clock;
     36     int child = 0;
     37    // printf("u%d
    ",u);
     38     for(int i=0; i<G[u].size(); i++){
     39         int v = G[u][i];
     40         Edge e = (Edge){u, v};
     41         if(!pre[v]){
     42             S.push(e);
     43             child++;
     44             int lowv = dfs(v, u);
     45             lowu = min(lowu, lowv);
     46             if(lowv >= pre[u]){
     47                 iscut[u] = true;
     48                 bcc_cnt++; bcc[bcc_cnt].clear();
     49                 for(;;)
     50                 {
     51                     Edge x = S.top(); S.pop();
     52                     if(bccno[x.u] != bcc_cnt) 
     53            {
     54                         bcc[bcc_cnt].push_back(x.u);
     55                         bccno[x.u] = bcc_cnt;
     56                     }
     57                     if(bccno[x.v] != bcc_cnt) {
     58                         bcc[bcc_cnt].push_back(x.v);
     59                         bccno[x.v] = bcc_cnt;
     60                     }
     61                     if(x.u == u && x.v == v) break;
     62                 }
     63             }
     64         }
     65         else if(pre[v] < pre[u] && v != fa){
     66             S.push(e);
     67             lowu = min(lowu, pre[v]);
     68            // printf("fan lowu%d
    ",lowu);
     69            // printf("fan%d %d
    ",e.u,e.v);
     70         }
     71     }
     72     if(fa < 0 && child == 1) iscut[u] = 0;
     73     low[u]=lowu;
     74     return lowu;
     75 }
     76 
     77 void find_bcc(int n){
     78     memset(pre, 0, sizeof(pre));
     79     memset(iscut, 0, sizeof(iscut));
     80     memset(bccno, 0, sizeof(bccno));
     81     dfs_clock = bcc_cnt = 0;
     82     for(int i=0; i<n; i++){
     83         if(!pre[i]) dfs(i, -1);
     84     }
     85 }
     86 
     87 int main(){
     88     int m, u, v, n;
     89     freopen("test2.in","r",stdin);
     90     scanf("%d%d", &n, &m);
     91 
     92     for(int i=0; i<m; i++){
     93         cin>>u>>v;
     94         G[u].push_back(v);
     95         G[v].push_back(u);
     96     }
     97 
     98     find_bcc(n);
     99 
    100     printf("%d
    ", bcc_cnt);    //双连通分量的个数
    101     for(int i=1; i<=bcc_cnt; i++){  //输出每个双连通分量
    102         for(int j=0; j<bcc[i].size(); j++){
    103             printf("%d ", bcc[i][j]);
    104         }
    105         putchar('
    ');
    106     }
    107   
    108     return 0;
    109 }
    View Code

    6、边双连通分量

     1 //边双连通分量的求解非常简单,因为边双连通分量之间没有公共边,而且桥不在任意一个边双连通分量中,所以算法十分简单,即先一次DFS找到所有桥,再一次DFS(排除了桥)找到边双连通分量。 
     2 //PS:当然可以用一次DFS实现。 
     3 struct Edge{
     4     int u,v;
     5     Edge(int u=0,int v=0):u(u),v(v){}
     6 }e[maxm];
     7 int n,m,stamp,dfn[maxn],low[maxn],bccno[maxn],bcc_cnt;
     8 vector<int> vec[maxn],bcc[maxn];
     9 bool g[maxn][maxn],isbridge[maxm];
    10 
    11 void tarjan(int u,int fa)
    12 {
    13     int tmp;
    14     dfn[u]=low[u]=++stamp;
    15     for(int i=0;i<vec[u].size();i++)
    16     {
    17         tmp=e[vec[u][i]].v;
    18         if(!dfn[tmp])
    19         {
    20             tarjan(tmp,u);
    21             low[u]=min(low[u],low[tmp]);
    22             if(low[tmp]>dfn[u])
    23                 isbridge[vec[u][i]]=isbridge[vec[u][i]^1]=1;
    24         }
    25         else if(dfn[tmp]<dfn[u] && tmp!=fa)
    26         {
    27             low[u]=min(low[u], dfn[tmp]);
    28         }
    29     }
    30 }
    31 
    32 void dfs(int u)
    33 {
    34     dfn[u]=1;
    35     bccno[u]=bcc_cnt;
    36     for(int i=0;i<vec[u].size();i++)
    37     {
    38         int tmp=vec[u][i];
    39         if(isbridge[tmp])
    40             continue;
    41         if(!dfn[e[tmp].v])
    42         {
    43             dfs(e[tmp].v);
    44         }
    45     }
    46 }
    47 
    48 void find_ebcc(){
    49     bcc_cnt=stamp=0;
    50     memset(dfn,0,sizeof(dfn));
    51     memset(low,0,sizeof(low));
    52     memset(isbridge,0,sizeof(isbridge));
    53     memset(bccno,0,sizeof(bccno));
    54     memset(bcc,0,sizeof(bcc));
    55     for(int i=1;i<=n;i++)
    56         if(!dfn[i])
    57             tarjan(i, -1);
    58     memset(dfn,0,sizeof(dfn));
    59     for(int i=1;i<=n;i++)
    60     {
    61         if(!dfn[i])
    62         {
    63             bcc_cnt++;
    64             dfs(i);
    65         }
    66     }               
    67 }
    View Code

    二、数论

    1、最大公因数

    1 int gcd(int a,int b)
    2 {
    3     return b?gcd(b,a%b):a;
    4 }
    View Code

    2、最小公倍数

    1 int gcd(int a,int b)
    2 {
    3     return b?gcd(b,a%b):a;
    4 }
    5 int lcm(int a,int b)
    6 {
    7     return a*b/gcd(a,b);
    8 }
    View Code

    3、快速幂(ab

     1 #include <cstdio>
     2 #define ll long long
     3 const int maxn=1e9+7;
     4 ll ksm(int a,int b)
     5 {
     6     ll s=1;
     7     while (b)
     8     {
     9         if (b&1) s=s*a%maxn;
    10         a=1ll*a*a%maxn;
    11         b>>=1;
    12     }
    13     return s;
    14 }
    View Code

    4、欧拉筛法求素数

     1 #include <cstdio>
     2 int p[100005],pt;   // 存素数 
     3 bool f[100005];
     4 void makeprime()
     5 {
     6     int i,j;
     7     for (i=2;i<=100005;i++)
     8     {
     9         if (!f[i]) p[++pt]=i;
    10         for (j=1;j<=pt && 1ll*i*p[j]<=100005;j++)
    11         {
    12             f[i*p[j]]=1;
    13             if (!(i%p[j])) break;
    14         }
    15     }
    16 //    for (i=1;i<=pt;i++) printf("%d ",p[i]); 
    17     return;
    18 }
    19 int main()
    20 {
    21     makeprime();
    22     return 0;
    23 }
    View Code

    5、逆元求组合数

     1 #include <cstdio>
     2 #define ll long long
     3 const ll maxn=1e9+7;
     4 int n,m,K;
     5 ll ans,fac[900005],inv[900005];
     6 ll C(int n,int m)  //  n>=m 
     7 {
     8     return fac[n]*inv[m]%maxn*inv[n-m]%maxn;
     9 }
    10 ll ksm(int a,int b)
    11 {
    12     ll s=1;
    13     while (b)
    14     {
    15         if (b&1) s=s*a%maxn;
    16         a=1ll*a*a%maxn;
    17         b>>=1;
    18     }
    19     return s;
    20 }
    21 int main()
    22 {
    23     int i,j;
    24     scanf("%d%d",&n,&m);
    25     for (fac[0]=inv[0]=i=1;i<900005;i++) fac[i]=fac[i-1]*i%maxn;
    26     inv[900004]=ksm(fac[900004],maxn-2);
    27     for (i=900004;i>=1;i--) inv[i]=inv[i+1]*(i+1)%maxn;
    28     printf("%lld
    ",C(n,m));
    29     return 0;
    30 }
    View Code

    6、杨辉三角求组合数

    1 #include <cstdio>
     2 const int maxn=1e9+7;
     3 int c[1005][1005];
     4 int main()
     5 {
     6     int i,j;
     7     c[0][0]=1;
     8     for (i=1;i<=1000;i++) c[i][0]=c[i][i]=1;
     9     for (i=2;i<=1000;i++)
    10       for (j=1;j<i;j++)
    11         c[i][j]=(c[i-1][j]+c[i-1][j-1])%maxn;
    12 /*    for (i=0;i<=10;i++)
    13     {
    14         for (j=0;j<=i;j++) printf("%d ",c[i][j]);
    15         printf("
    ");
    16     } */
    17     return 0;
    18 }
    View Code

    7、埃氏筛法求欧拉函数

     1 #include <cstdio>
     2 #define ll long long
     3 int eul[10000005],m;
     4 int main()
     5 {
     6     int i,j;
     7     scanf("%d",&m);  // 1~m 的欧拉函数 
     8     for (i=1;i<=m;i++) eul[i]=i;  
     9     for (i=2;i<=m;i++)
    10       if (eul[i]==i)
    11         for (j=i;j<=m;j+=i)
    12           eul[j]=eul[j]/i*(i-1);
    13     return 0;    
    14 }
    View Code

    8、质因数分解求欧拉函数

    1 #include <cstdio>
     2 #define ll long long
     3 int eul[10000005],n;
     4 ll euler_phi(int n)
     5 {
     6     ll s=n;
     7     for (int i=2;i*i<=n;i++)
     8       if (!(n%i))
     9         for (s=s/i*(i-1);!(n%i);n/=i);
    10       if (n!=1) s=s/n*(n-1);
    11       return s;
    12 }
    13 int main()
    14 {
    15     int i,j;
    16     scanf("%d",&n);  
    17     printf("%lld",euler_phi(n));
    18     return 0;    
    19 }
    View Code

    9、扩展欧几里得(ax+by=c的一组特解x,y)

     1 int exgcd(int a,int b,int &x,int &y)
     2 {
     3     if (!b) 
     4     {
     5         x=1,y=0;
     6         return a;
     7     }
     8     int ans=exgcd(b,a%b,x,y);
     9     t=x,x=y,y=t-(a/b)*y;
    10     return ans;
    11 }
    View Code

    三、数据结构

    1、单调队列

     1 #include <cstdio>
     2 int n,m,a[1000005];
     3 int q1[1000005],h1,t1,s1[1000005],p1,d1[1000005];  // 求定长滑动区间内的最大值 
     4 int q2[1000005],h2,t2,s2[1000005],p2,d2[1000005];  // 求定长滑动区间内的最小值
     5 int main()
     6 {
     7     int i,j,x;
     8     scanf("%d%d",&n,&m);
     9     scanf("%d",&x);
    10     q1[1]=q2[1]=x;
    11     h1=h2=t1=t2=d1[1]=d2[1]=1;
    12     for (i=2;i<=m;i++)
    13     {
    14         scanf("%d",&x);
    15         while (q1[t1]<=x && t1>=h1) t1--;
    16         q1[++t1]=x;  d1[t1]=i;
    17         
    18         while (q2[t2]>=x && t2>=h2) t2--;
    19         q2[++t2]=x;  d2[t2]=i;
    20     }
    21     s1[1]=q1[1];  s2[1]=q2[1];
    22     p1=p2=1;
    23     for (i=m+1;i<=n;i++)
    24     {
    25         scanf("%d",&x);
    26         while (q1[t1]<=x && t1>=h1) t1--;
    27         q1[++t1]=x;  d1[t1]=i;
    28         while (i-d1[h1]>=m) h1++;
    29         s1[++p1]=q1[h1];
    30         
    31         while (q2[t2]>=x && t2>=h2) t2--;
    32         q2[++t2]=x;  d2[t2]=i;
    33         while (i-d2[h2]>=m) h2++;
    34         s2[++p2]=q2[h2];
    35     }
    36     for (i=1;i<=p2;i++)
    37       printf("%d ",s2[i]);
    38     printf("
    ");
    39     
    40     for (i=1;i<=p1;i++)
    41       printf("%d ",s1[i]);
    42     return 0;
    43 }
    View Code

    2、字典树

     1 #include <cstdio>
     2 #define ll long long
     3 int n,cnt=1,f[12000015][2],num[12000015];   //  树的深度 * 每个结点分叉数 * 字符个数 
     4 ll a[100005],ans;
     5 void add(ll x)
     6 {
     7     int now=1,i,j;
     8     for (i=0;i<60;i++)
     9     {
    10         j=((x&(1ll<<i))>>i);
    11         if (!f[now][j]) f[now][j]=++cnt;
    12         num[f[now][j]]++;
    13         now=f[now][j];
    14     }
    15     return;
    16 }
    17 void query(ll x)
    18 {
    19     int now=1,k,j;
    20     for (now=1,j=0;j<60;j++)
    21     {
    22         k=((x&(1ll<<j))>>j);
    23         ans+=num[f[now][k]];
    24         now=f[now][k];
    25       }
    26       return;
    27 }
    28 int main()
    29 {
    30     int i,j,k,now;
    31     scanf("%d",&n);
    32     for (i=1;i<=n;i++)
    33       scanf("%lld",&a[i]);
    34     for (i=1;i<=n;i++) add(a[i]);
    35     for (i=1;i<=n;i++) query(a[i]);
    36       printf("%lld
    ",ans);
    37       return 0;
    38 }
    View Code

    3、树状数组

     1 #include <cstdio>
     2 int n,m,k,a[100005],c[100005];
     3 int lowbit(int x)
     4 {
     5     return x&(-x);
     6 }
     7 void plus(int p,int x)
     8 {
     9     while (p<=n)
    10       c[p]+=x,
    11       p+=lowbit(p);
    12     return;
    13 }
    14 int getsum(int p)
    15 {
    16     int s=0;
    17     while (p)
    18       s+=c[p],
    19       p-=lowbit(p);
    20     return s;
    21 }
    22 int main()
    23 {
    24     int i,j,x,y;
    25     scanf("%d%d",&n,&m);
    26     for (i=1;i<=n;i++)
    27       scanf("%d",&a[i]),
    28       plus(i,a[i]);
    29     while (m--)
    30     {
    31         scanf("%d%d%d",&k,&x,&y);     
    32         //  k=0  求区间[x,y]的和  
    33         //  k=1  a[x]的值加上y 
    34         if (k) plus(x,y);
    35         else printf("%d
    ",getsum(y)-getsum(x-1));
    36     }
    37     return 0;
    38 } 
    View Code

    4、线段树

     1 #include <cstdio>
     2 int n,m,s,t,p,f[4000005],a[1000005];   //  f[4*n] 
     3 void build(int l,int r,int id)
     4 {
     5     if (l==r)
     6     {
     7         f[id]=a[l];
     8         return;
     9     }
    10     int ls=id<<1,rs=ls|1,mid=(l+r)>>1;
    11     build(l,mid,ls);
    12     build(mid+1,r,rs);
    13     f[id]=f[ls]+f[rs];
    14     return;
    15 }
    16 void modify(int l,int r,int id)
    17 {
    18     if (l==r)
    19     {
    20         f[id]+=t;
    21         return;
    22     }
    23     int ls=id<<1,rs=ls|1,mid=(l+r)>>1;
    24     if (s<=mid) modify(l,mid,ls);
    25     else modify(mid+1,r,rs);
    26     f[id]=f[ls]+f[rs];
    27     return;
    28 }
    29 int query(int l,int r,int id)
    30 {
    31     if (s<=l && r<=t) return f[id];
    32     int sum=0,ls=id<<1,rs=ls|1,mid=(l+r)>>1;
    33     if (s<=mid) sum=query(l,mid,ls);
    34     if (t>mid) sum+=query(mid+1,r,rs);
    35     return sum;
    36 }
    37 int main()
    38 {
    39     int i,j;
    40     scanf("%d%d",&n,&m);
    41     build(1,n,1);
    42     while (m--)
    43     {
    44         scanf("%d%d%d",&p,&s,&t);
    45         //  p=0  a[s]的值加上t
    46         //  p=1  求区间[s,t]的和 
    47         if (!p) modify(1,n,1);
    48         else printf("%d
    ",query(1,n,1));
    49     }
    50     return 0;
    51 }
    View Code

    四、动态规划

    1、01背包

    (1)二维

     1 #include <cstdio>
     2 int n,m,w[1005],c[1005],f[1005][1005];
     3 int max(int x,int y)
     4 {
     5     return x>y?x:y;
     6 }
     7 int main()
     8 {
     9     int i,j,k;
    10     scanf("%d%d",&n,&m);
    11     for (i=1;i<=n;i++)
    12       scanf("%d%d",&w[i],&c[i]);
    13     for (i=1;i<=n;i++)
    14       for (j=0;j<=m;j++)
    15       {
    16           f[i][j]=f[i-1][j];
    17           if (j>=w[i]) f[i][j]=max(f[i][j],f[i-1][j-w[i]]+c[i]);
    18       }   
    19     printf("%d",f[n][m]);
    20     return 0;
    21 }
    View Code

    (2)一维

     1 #include <cstdio>
     2 int n,m,w[1005],c[1005],f[1005];
     3 int max(int x,int y)
     4 {
     5     return x>y?x:y;
     6 }
     7 int main()
     8 {
     9     int i,j,k;
    10     scanf("%d%d",&n,&m);
    11     for (i=1;i<=n;i++)
    12       scanf("%d%d",&w[i],&c[i]);
    13     for (i=1;i<=n;i++)
    14       for (j=m;j>=w[i];j--)
    15         f[j]=max(f[j],f[j-w[i]]+c[i]);  
    16     printf("%d",f[m]);
    17     return 0;
    18 }
    View Code

    2、完全背包

     1 #include <cstdio>
     2 int n,m,w[1005],c[1005],f[1005];
     3 int max(int x,int y)
     4 {
     5     return x>y?x:y;
     6 }
     7 int main()
     8 {
     9     int i,j,k;
    10     scanf("%d%d",&n,&m);
    11     for (i=1;i<=n;i++)
    12       scanf("%d%d",&w[i],&c[i]);
    13     for (i=1;i<=n;i++)
    14       for (j=w[i];j<=m;j++)
    15         f[j]=max(f[j],f[j-w[i]]+c[i]);  
    16     printf("%d",f[m]);
    17     return 0;
    18 }
    View Code

    3、多重背包

    (1)普通二维

     1 #include <cstdio> 
     2 int n,m,w[1005],v[1005],num[1005],f[1005][2005];
     3 int min(int x,int y)
     4 {
     5     return x<y?x:y;
     6 }
     7 int max(int x,int y)
     8 {
     9     return x>y?x:y;
    10 }
    11 int main()
    12 {
    13     int i,j,k,t;
    14     scanf("%d%d",&n,&m);
    15     for (i=1;i<=n;i++) 
    16       scanf("%d%d%d",&w[i],&v[i],&num[i]);
    17     for(i=1;i<=n;i++)
    18       for(j=w[i];j<=m;j++)
    19       {
    20         t=min(num[i],j/w[i]);//可以放的个数
    21         for(k=0;k<=t;k++)
    22           f[i][j]=max(f[i][j],f[i-1][j-k*w[i]]+k*v[i]);
    23       }
    24     printf("%d",f[n][m]);
    25     return 0;
    26 }
    View Code

    (2)一维

     1 #include <cstdio> 
     2 int n,m,w[1005],v[1005],num[1005],f[2005];
     3 int min(int x,int y)
     4 {
     5     return x<y?x:y;
     6 }
     7 int max(int x,int y)
     8 {
     9     return x>y?x:y;
    10 }
    11 int main()
    12 {
    13     int i,j,k,t;
    14     scanf("%d%d",&n,&m);
    15     for (i=1;i<=n;i++) 
    16       scanf("%d%d%d",&w[i],&v[i],&num[i]);
    17     for(i=1;i<=n;i++)
    18     {
    19         t=min(num[i],j/w[i]);//可以放的个数
    20         for(k=0;k<=t;k++)
    21           for(j=m;j>=w[i]*k;j--)
    22             f[j]=max(f[j],f[j-k*w[i]]+k*v[i]);
    23     }
    24     printf("%d",f[m]);
    25     return 0;
    26 }
    View Code

    (3)二进制优化

     1 #include <cstdio>
     2 int n,m,count,w[105],v[105],num[105],f[100005];
     3 int max(int x,int y)
     4 {
     5     return x>y?x:y;
     6 }
     7 int main()
     8 {
     9     int i,j,p,g;
    10     scanf("%d%d",&n,&m);
    11     for(i=1;i<=n;i++)
    12       scanf("%d%d%d",&w[i],&v[i],&num[i]);
    13     for(i=1;i<=n;i++)
    14     {
    15         p=g=0;
    16         while(num[i]>g)
    17         {
    18             for(j=m;j>=w[i]*g;j--)
    19               f[j]=max(f[j],f[j-w[i]*g]+v[i]*g);
    20             num[i]-=g;  g=1<<p;  p++;
    21         }
    22         for(j=m;j>=w[i]*num[i];j--)
    23           f[j]=max(f[j],f[j-w[i]*num[i]]+v[i]*num[i]);
    24     }
    25     printf("%d",f[m]);
    26     return 0;
    27 }
    View Code

    4、最长不下降子序列

    (1)O(n2)

     1 #include <cstdio>
     2 int n,a[40005],f[40005],ans;
     3 int main()
     4 {
     5     int i,j;
     6     scanf("%d",&n);
     7     for (i=1;i<=n;i++) scanf("%d",&a[i]);
     8     f[1]=1;
     9     for (i=2;i<=n;i++)
    10     {
    11         for (j=1;j<i;j++)
    12           if (a[j]<=a[i] && f[j]>f[i])
    13             f[i]=f[j];
    14         f[i]++;
    15     }
    16     for (i=1;i<=n;i++)
    17       if (f[i]>ans)
    18         ans=f[i];
    19     printf("%d
    ",ans);    
    20     return 0;
    21 }
    View Code

    (2)O(n log n)

     1 #include <algorithm>
     2 #include <cstdio>
     3 int n,a[40005],d[40005];
     4 int main()
     5 {
     6     int i,j,len=1;
     7     scanf("%d",&n);
     8     for (i=1;i<=n;i++) scanf("%d",&a[i]);
     9     d[1]=a[1];  //初始化 
    10     for (i=2;i<=n;i++)
    11     {
    12         if (a[i]>=d[len]) d[++len]=a[i];  //如果可以接在len后面就接上,如果是最长上升子序列,这里变成> 
    13         else  //否则就找一个最该替换的替换掉 
    14         {
    15             j=std::upper_bound(d+1,d+len+1,a[i])-d;  //找到第一个大于它的d的下标,如果是最长上升子序列,这里变成lower_bound 
    16             d[j]=a[i]; 
    17         }
    18     }
    19     printf("%d
    ",len);    
    20     return 0;
    21 }
    View Code

    5、最长公共子序列

    (1)普通

     1 #include <cstring>
     2 #include <cstdio>
     3 char a[1005],b[1005];
     4 int lena,lenb,f[1005][1005];
     5 int max(int x,int y)
     6 {
     7     return x>y?x:y;
     8 }
     9 int main()
    10 {
    11     int i,j;
    12     scanf("%s%s",a,b);
    13     lena=strlen(a);
    14     lenb=strlen(b);
    15     f[0][0]=(a[0]==b[0]);
    16     for(i=1;i<=lena;i++)
    17       for(j=1;j<=lenb;j++)
    18       {
    19         if(a[i-1]==b[j-1])
    20           f[i][j]=f[i-1][j-1]+1;
    21         else
    22           f[i][j]=max(f[i-1][j],f[i][j-1]);
    23       }
    24     printf("%d
    ",f[lena][lenb]);
    25     return 0;
    26 }
    View Code

    (2)打印路径

     1 #include<cstring>
     2 #include<cstdio>
     3 char a[1005],b[1005];
     4 int f[1005][1005],lena,lenb,flag[1005][1005];
     5 void write(int i,int j)
     6 {
     7     if(i==0||j==0) return;  //递归终止条件
     8     if(!flag[i][j])
     9     {
    10         write(i-1,j-1);
    11         printf("%c",a[i-1]);
    12     }
    13     else if(flag[i][j]==1)
    14     {
    15         write(i-1,j);
    16     }
    17     else if(flag[i][j]=-1)
    18     {
    19         write(i,j-1);
    20     }
    21 }
    22 int main()
    23 {
    24     int i,j;
    25     scanf("%s%s",a,b);
    26     lena=strlen(a);
    27     lenb=strlen(b);
    28     for(i=1;i<=lena;i++)
    29       for(j=1;j<=lenb;j++)
    30       {
    31         if(a[i-1]==b[j-1])
    32         {
    33             f[i][j]=f[i-1][j-1]+1;
    34             flag[i][j]=0;///来自于左上方
    35         }
    36         else
    37         {
    38             if(f[i-1][j]>f[i][j-1])
    39             {
    40                 f[i][j]=f[i-1][j];
    41                 flag[i][j]=1;///来自于左方
    42             }
    43             else
    44             {
    45                 f[i][j]=f[i][j-1];
    46                 flag[i][j]=-1;///来自于上方
    47             }
    48         }
    49     }
    50     write(lena,lenb);
    51     return 0;
    52 }
    View Code

    6、区间动规

    1 int dp(int l,int r)
    2 {
    3     if (used[l][r]) return f[l][r];
    4     used[l][r]=1;
    5     if (l==r) return f[l][r]=0;
    6     for (int i=l;i<r;i++)    
    7         f[l][r]=min(f[l][r],dp(l,i)+dp(i+1,r)+w[l][r]);      
    8     return f[l][r];    
    9 }
    View Code

    五、高精度

    1、高精加高精

     1 #include <cstring>
     2 #include <cstdio>
     3 struct note{
     4     int len,v[1005];
     5 };
     6 int max(int x,int y)
     7 {
     8     return x>y?x:y;
     9 }
    10 note operator + (note a,note b)
    11 {
    12     note c;
    13     memset(c.v,0,sizeof(c.v));
    14     int i,lenc=max(a.len,b.len);
    15     for (i=1;i<=lenc;i++)
    16       c.v[i]+=a.v[i]+b.v[i],
    17       c.v[i+1]+=c.v[i]/10,
    18       c.v[i]%=10;
    19     while (c.v[lenc+1]) lenc++;
    20     c.len=lenc;
    21     return c;
    22 }
    View Code

    2、高精减高精

     1 #include <cstdio>
     2 struct note{
     3     int len,v[10005];
     4 };
     5 char s1[10005],s2[10005];
     6 bool operator < (note a,note b)
     7 {
     8     if (a.len!=b.len) return a.len<b.len;
     9     for (int i=a.len;i>=1;i--)
    10       if (a.v[i]!=b.v[i])
    11         return a.v[i]<b.v[i];
    12     return 0;
    13 }
    14 note operator - (note a,note b)
    15 {
    16     note c;
    17     int fg=1;
    18     if (a<b) fg=-1,c=a,a=b,b=c;
    19     int i,lenc=a.len;
    20     for (i=1;i<=lenc;i++)
    21     {
    22         if (a.v[i]<b.v[i]) a.v[i]+=10,a.v[i+1]--;
    23         c.v[i]=a.v[i]-b.v[i];
    24     }
    25     while (!c.v[lenc] && lenc>1) lenc--;
    26     c.len=lenc;
    27     c.v[lenc]*=fg;
    28     return c;
    29 }
    View Code

    3、高精乘单精

     1 #include <cstdio>
     2 struct note{
     3     int v[1000],len;
     4 };
     5 note operator * (note a,int b)
     6 {
     7     note c;
     8     int w=0;
     9     int i,lena=a.len,lenc;
    10     for (i=1;i<=lena;i++)
    11       c.v[i]=a.v[i]*b+w,
    12       w=c.v[i]/10,
    13       c.v[i]%=10;
    14     for(lenc=lena;w;c.v[++lenc]=w%10,w/=10);
    15     c.len=lenc;
    16     return c;
    17 }
    View Code

    4、高精乘高精

     1 #include <cstring>
     2 #include <cstdio>
     3 struct note{
     4     int len,v[10005];
     5 };
     6 note operator * (note a,note b)
     7 {
     8    note c;
     9    memset(c.v,0,sizeof(c.v));
    10    int i,j,lena=a.len,lenb=b.len,lenc=a.len+b.len-1;
    11    for (i=1;i<=lena;i++)
    12       for (j=1;j<=lenb;j++)
    13          c.v[i+j-1]+=a.v[i]*b.v[j];
    14    for (i=1;i<=lenc;i++)
    15       c.v[i+1]+=c.v[i]/10,
    16       c.v[i]%=10;
    17    if (c.v[lenc+1]) lenc++;
    18    for (;c.v[lenc]>=10;lenc++) c.v[lenc+1]=c.v[lenc]/10,c.v[lenc]%=10;
    19      c.len=lenc;
    20    return c;
    21 }
    View Code

    5、高精除单精

     1 #include <cstdio>
     2 struct note{
     3     int v[1000],len;
     4 };
     5 note operator / (note a,int b)
     6 {
     7     note c;
     8     int i,lena=a.len,lenc=1,x=0,t;
     9     for (i=lena,x=a.v[lena];x<b && i>1;x=x*10+a.v[--i]);
    10     c.v[1]=x/b;  x%=b;
    11     for (i--;i>=1;i--)
    12       x=x*10+a.v[i],
    13       c.v[++lenc]=x/b,
    14       x%=b;
    15     for (i=1;i<=lenc/2;i++)
    16       c.v[i]^=c.v[lenc-i+1],c.v[lenc-i+1]^=c.v[i],c.v[i]^=c.v[lenc-i+1];
    17     c.len=lenc;
    18     return c;
    19 }
    View Code

    六、其它

    1、读入优化

    1 int read()
    2 {
    3     int s=0;
    4     char ch=getchar();
    5     while (ch<'0' || ch>'9') ch=getchar();
    6     while (ch>='0' && ch<='9') 
    7       s=s*10+ch-'0',ch=getchar();
    8     return s;
    9 }
    View Code

    2、输出优化

    1 void write(int x)
    2 {
    3     if (x>=10) write(x/10);
    4     putchar(x%10+'0');
    5     return;
    6 }
    View Code

    3、倍增LCA

     1 #include <cstdio>
     2 struct node{
     3     int u,v,nex;
     4 }g[1000005];
     5 int n,Q,root,fir[500005],num,f[500005][20],d[500005];
     6 void add(int x,int y)
     7 {
     8     g[++num].u=y;  g[num].nex=fir[x];  fir[x]=num;
     9     return;
    10 }
    11 void dfs(int x,int fa)
    12 {
    13     int i,k,v;
    14     f[x][0]=fa;  d[x]=d[fa]+1;
    15     for (i=1;i<=19;i++)
    16       f[x][i]=f[f[x][i-1]][i-1];
    17     for (k=fir[x];k;k=g[k].nex)
    18     {
    19         v=g[k].u;
    20         if (v==fa) continue;
    21         dfs(v,x);
    22     }
    23     return;
    24 }
    25 int lca(int x,int y)
    26 {
    27     int i,j;
    28     if (d[x]>d[y]) x^=y,y^=x,x^=y;
    29     for (i=19;i>=0;i--)
    30       if (d[f[y][i]]>=d[x])
    31         y=f[y][i];
    32     if (x==y) return x;
    33     for (i=19;i>=0;i--)
    34       if (f[x][i]!=f[y][i])
    35         x=f[x][i],y=f[y][i];
    36     return f[x][0];
    37 }
    38 int main()
    39 {
    40     int i,j,k,x,y;
    41     scanf("%d%d%d",&n,&Q,&root);
    42     for (i=1;i<n;i++)
    43       scanf("%d%d",&x,&y),
    44       add(x,y),add(y,x);
    45     dfs(root,0);
    46     while (Q--)
    47     {
    48         scanf("%d%d",&x,&y);
    49         printf("%d
    ",lca(x,y));
    50     }
    51     return 0;
    52 }
    View Code

    4、计时函数

     1 #include <cstdio>
     2 #include <ctime>
     3 int main()
     4 {
     5     clock_t st, ed;
     6     st=clock();
     7     for(int i=0;i<100000000;i++)
     8     {
     9         i-=1;    i+=1;
    10     }
    11     ed=clock();
    12     printf("Total time:%.2fs",(double)(ed-st)/CLOCKS_PER_SEC); 
    13     return 0;
    14 }
    View Code

    暂存

     1 #include <cstdio>
     2 #include <set>
     3 #define ll long long
     4 std::set<int> s;
     5 std::set<int>::iterator p;
     6 int n,op,x,k,cnt[100005];
     7 ll ans;
     8 int main()
     9 {
    10     scanf("%d",&n);
    11     while (n--)
    12     {
    13         scanf("%d%d",&op,&x);
    14         if (op==1)
    15         {
    16             ans+=x;
    17             if (s.empty()) continue;
    18             p=s.lower_bound(x);
    19             if (p==s.begin()) continue;
    20             k=*(--p);
    21             ans-=k;
    22             cnt[k]--;
    23             if (!cnt[k]) s.erase(k);
    24         }
    25         else s.insert(x),cnt[x]++;
    26     }
    27     printf("%lld
    ",ans);
    28     return 0;
    29 }
    View Code
  • 相关阅读:
    spark内存概述
    Spark Streaming使用Kafka保证数据零丢失
    usbmanger android 底下USB的工作模式
    TextView赋值int型,并显示
    Android jni编辑.so库
    opencv使用convexityDefects计算轮廓凸缺陷
    opencv轮廓处理函数详细
    slam相关知识
    VS2010+PCL+openni配置
    共有65款 计算机视觉库/人脸识别开源软件
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/9702576.html
Copyright © 2011-2022 走看看