• 专题训练之LCA


    推荐几个博客:https://www.cnblogs.com/JVxie/p/4854719.html Tarjan离线算法的基本思路及其算法实现

    https://blog.csdn.net/shahdza/article/details/7779356 LCA题集

    http://www.cnblogs.com/zhouzhendong/p/7256007.html LCA的三种算法介绍

    模板(题):

    1.(POJ1470)http://poj.org/problem?id=1470

    Tarjan离线算法

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<iostream>
      5 using namespace std;
      6 const int maxn=1010;
      7 const int maxm=500010;
      8 struct Edge{
      9     int to,nxt;
     10 }edge[maxn*2];
     11 struct Query{
     12     int q,nxt;
     13     int index;
     14 }query[maxm*2];
     15 int f[maxn],anc[maxn];
     16 bool vis[maxn];
     17 int head[maxn],tot;
     18 int ans[maxm],h[maxm],tt,Q;
     19 bool flag[maxn];
     20 int num[maxn];
     21 
     22 int find(int x)
     23 {
     24     if ( f[x]==-1 ) return x;
     25     return f[x]=find(f[x]);
     26 }
     27 
     28 void merge(int x,int y)
     29 {
     30     int fx=find(x);
     31     int fy=find(y);
     32     if ( fx!=fy ) f[fx]=fy;
     33 }
     34 
     35 void addedge(int u,int v)
     36 {
     37     edge[tot].to=v;
     38     edge[tot].nxt=head[u];
     39     head[u]=tot++;
     40 }
     41 
     42 void addquery(int u,int v,int index)
     43 {
     44     query[tt].q=v;
     45     query[tt].nxt=h[u];
     46     query[tt].index=index;
     47     h[u]=tt++;
     48     query[tt].q=u;
     49     query[tt].nxt=h[v];
     50     query[tt].index=index;
     51     h[v]=tt++;
     52 }
     53 
     54 void init()
     55 {
     56     tot=0;
     57     memset(head,-1,sizeof(head));
     58     tt=0;
     59     memset(h,-1,sizeof(h));
     60     memset(vis,false,sizeof(vis));
     61     memset(f,-1,sizeof(f));
     62     memset(anc,0,sizeof(anc));
     63 }
     64 
     65 void LCA(int u)
     66 {
     67     anc[u]=u;
     68     vis[u]=true;
     69     for ( int i=head[u];i!=-1;i=edge[i].nxt )
     70     {
     71         int v=edge[i].to;
     72         if ( vis[v] ) continue;
     73         LCA(v);
     74         merge(u,v);
     75         anc[find(u)]=u;
     76     }
     77     for ( int i=h[u];i!=-1;i=query[i].nxt )
     78     {
     79         int v=query[i].q;
     80         if ( vis[v] ) ans[query[i].index]=anc[find(v)];
     81     }
     82 }
     83 
     84 int main()
     85 {
     86     int n,u,v,k;
     87     while ( scanf("%d",&n)!=EOF )
     88     {
     89         init();
     90         memset(flag,false,sizeof(flag));
     91         for ( int i=1;i<=n;i++ )
     92         {
     93             scanf("%d:(%d)",&u,&k);
     94             while ( k-- )
     95             {
     96                 scanf("%d",&v);
     97                 flag[v]=true;
     98                 addedge(u,v);
     99                 addedge(v,u);
    100             }
    101         }
    102         scanf("%d",&Q);
    103         for ( int i=0;i<Q;i++ )
    104         {
    105             char ch;
    106             cin>>ch;
    107             scanf("%d %d)",&u,&v);
    108             addquery(u,v,i);
    109         }
    110         int root;
    111         for ( int i=1;i<=n;i++ )
    112         {
    113             if ( !flag[i] )
    114             {
    115                 root=i;
    116                 break;
    117             }
    118         }
    119         LCA(root);
    120         memset(num,0,sizeof(num));
    121         for ( int i=0;i<Q;i++ ) num[ans[i]]++;
    122         for ( int i=1;i<=n;i++ )
    123         {
    124             if ( num[i]>0 ) printf("%d:%d
    ",i,num[i]);
    125         }
    126     }
    127     return 0;
    128 }
    POJ1470

    2.(POJ1330)http://poj.org/problem?id=1330

    倍增法在线算法

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 using namespace std;
      6 const int maxn=1e4+10;
      7 const int DEG=20;
      8 struct Edge{
      9     int to,nxt;
     10 }edge[maxn*2];
     11 int head[maxn],tot;
     12 int fa[maxn][DEG]; //fa[i][j]表示节点i的第2^j个祖先 
     13 int deg[maxn];
     14 bool flag[maxn];
     15 
     16 void addedge(int u,int v)
     17 {
     18     edge[tot].to=v;
     19     edge[tot].nxt=head[u];
     20     head[u]=tot++;
     21 }
     22 
     23 void init()
     24 {
     25     tot=0;
     26     memset(head,-1,sizeof(head));
     27 }
     28 
     29 void BFS(int root)
     30 {
     31     queue<int>que;
     32     deg[root]=0;
     33     fa[root][0]=root;
     34     que.push(root);
     35     while ( !que.empty() ) 
     36     {
     37         int tmp=que.front();
     38         que.pop();
     39         for ( int i=1;i<DEG;i++ ) fa[tmp][i]=fa[fa[tmp][i-1]][i-1];
     40         for ( int i=head[tmp];i!=-1;i=edge[i].nxt )
     41         {
     42             int v=edge[i].to;
     43             if ( v==fa[tmp][0] ) continue;
     44             deg[v]=deg[tmp]+1;
     45             fa[v][0]=tmp;
     46             que.push(v);
     47         }
     48     }
     49 }
     50 
     51 int LCA(int u,int v)
     52 {
     53     if ( deg[u]>deg[v] ) swap(u,v);
     54     int hu=deg[u],hv=deg[v];
     55     int tu=u,tv=v;
     56     for ( int det=hv-hu,i=0;det;det>>=1,i++ )
     57     {
     58         if ( det&1 ) tv=fa[tv][i];
     59     }
     60     if ( tu==tv ) return tu;
     61     for ( int i=DEG-1;i>=0;i-- )
     62     {
     63         if ( fa[tu][i]==fa[tv][i] ) continue;
     64         tu=fa[tu][i];
     65         tv=fa[tv][i];
     66     }
     67     return fa[tu][0];
     68 }
     69 
     70 int main()
     71 {
     72     int T,n,u,v;
     73     scanf("%d",&T);
     74     while ( T-- )
     75     {
     76         scanf("%d",&n);
     77         init();
     78         memset(flag,false,sizeof(flag));
     79         for ( int i=1;i<n;i++ )
     80         {
     81             scanf("%d%d",&u,&v);
     82             addedge(u,v);
     83             addedge(v,u);
     84             flag[v]=true;
     85         }
     86         int root;
     87         for ( int i=1;i<=n;i++ )
     88         {
     89             if ( !flag[i] )
     90             {
     91                 root=i;
     92                 break;
     93             }
     94         }
     95         BFS(root);
     96         scanf("%d%d",&u,&v);
     97         printf("%d
    ",LCA(u,v));
     98     }
     99     return 0;
    100 }
    POJ1330

    ST+DFS在线算法

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 const int maxn=10010;
      6 int rmq[maxn*2]; //即欧拉序列对应的深度序列 
      7 struct ST
      8 {
      9     int mm[2*maxn];
     10     int dp[2*maxn][20]; //最小值对应的下标
     11     void init(int n)
     12     {
     13         mm[0]=-1;
     14         for ( int i=1;i<=n;i++ )
     15         {
     16             mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
     17             dp[i][0]=i;
     18         }
     19         for ( int j=1;j<=mm[n];j++ )
     20         {
     21             for ( int i=1;i+(1<<j)-1<=n;i++ ) 
     22             {
     23                 if ( rmq[dp[i][j-1]]<rmq[dp[i+(1<<(j-1))][j-1]] ) dp[i][j]=dp[i][j-1];
     24                 else dp[i][j]=dp[i+(1<<(j-1))][j-1];    
     25             }
     26         }
     27     } 
     28     int query(int a,int b) //查询[a,b] 之间最小值的下标 
     29     {
     30         if ( a>b ) swap(a,b);
     31         int k=mm[b-a+1];
     32         if ( rmq[dp[a][k]]<=rmq[dp[b-(1<<k)+1][k]] ) return dp[a][k];
     33         else return dp[b-(1<<k)][k];
     34     }
     35 };
     36 struct Edge{
     37     int to,nxt;
     38 }edge[maxn*2];
     39 int tot,head[maxn];
     40 int F[maxn],P[maxn],cnt; //F为欧拉序(即DFS遍历的顺序),长度为2*n-1,从1开始;P为所有点第一次在F中出现的位置 
     41 ST st;
     42 
     43 void init()
     44 {
     45     tot=0;
     46     memset(head,-1,sizeof(head));
     47 }
     48 
     49 void addedge(int u,int v) //加边,无向边需要加两次 
     50 {
     51     edge[tot].to=v;
     52     edge[tot].nxt=head[u];
     53     head[u]=tot++;
     54 }
     55 
     56 void dfs(int u,int pre,int dep)
     57 {
     58     F[++cnt]=u;
     59     rmq[cnt]=dep;
     60     P[u]=cnt;
     61     for ( int i=head[u];i!=-1;i=edge[i].nxt )
     62     {
     63         int v=edge[i].to;
     64         if ( v==pre ) continue;
     65         dfs(v,u,dep+1);
     66         F[++cnt]=u;
     67         rmq[cnt]=dep;
     68     }
     69 }
     70 
     71 void LCA_init(int root,int num) //查询LCA前的初始化 
     72 {
     73     cnt=0;
     74     dfs(root,root,0);
     75     st.init(2*num-1);
     76 }
     77 
     78 int query(int u,int v) //查询LCA(u,v)的编号 
     79 {
     80     return F[st.query(P[u],P[v])];
     81 }
     82 bool flag[maxn];
     83 
     84 int main()
     85 {
     86     int T,N,u,v;
     87     scanf("%d",&T);
     88     while ( T-- )
     89     {
     90         scanf("%d",&N);
     91         init();
     92         memset(flag,false,sizeof(flag));
     93         for ( int i=1;i<N;i++ )
     94         {
     95             scanf("%d%d",&u,&v);
     96             addedge(u,v);
     97             addedge(v,u);
     98             flag[v]=true;
     99         }
    100         int root;
    101         for ( int i=1;i<=N;i++ )
    102         {
    103             if ( !flag[i] ) 
    104             {
    105                 root=i;
    106                 break;
    107             }
    108         }
    109         LCA_init(root,N);
    110         scanf("%d%d",&u,&v);
    111         printf("%d
    ",query(u,v));
    112     }
    113     return 0;
    114 }
    POJ1330

    练习题:

    1.(HDOJ2586)http://acm.hdu.edu.cn/showproblem.php?pid=2586

    题意:求给定两点之间的距离

    分析:如果t是u,v的最近公共祖先,那么d[u,v]=d[u,root]+d[v,root]-2*d[t,root],所以我们只需要在倍增算法的BFS中每次更新深度时同时把距离一起更新掉即可

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 using namespace std;
      6 const int maxn=4e4+10;
      7 const int DEG=20;
      8 const int inf=1e9;
      9 struct Edge{
     10     int to,nxt,w;
     11 }edge[maxn*2];
     12 int head[maxn],tot;
     13 int fa[maxn][DEG]; //fa[i][j]表示节点i的第2^j个祖先 
     14 int deg[maxn];
     15 bool flag[maxn];
     16 int n,d[maxn];
     17 
     18 void addedge(int u,int v,int w)
     19 {
     20     edge[tot].to=v;
     21     edge[tot].nxt=head[u];
     22     edge[tot].w=w;
     23     head[u]=tot++;
     24 }
     25 
     26 void init()
     27 {
     28     tot=0;
     29     memset(head,-1,sizeof(head));
     30 }
     31 
     32 void BFS(int root)
     33 {
     34     queue<int>que;
     35     for ( int i=1;i<=n;i++ ) d[i]=inf;
     36     d[root]=0;
     37     deg[root]=0;
     38     fa[root][0]=root;
     39     que.push(root);
     40     while ( !que.empty() ) 
     41     {
     42         int tmp=que.front();
     43         que.pop();
     44         for ( int i=1;i<DEG;i++ ) fa[tmp][i]=fa[fa[tmp][i-1]][i-1];
     45         for ( int i=head[tmp];i!=-1;i=edge[i].nxt )
     46         {
     47             int v=edge[i].to;
     48             int w=edge[i].w;
     49             if ( v==fa[tmp][0] ) continue;
     50             deg[v]=deg[tmp]+1;
     51             d[v]=min(d[v],d[tmp]+w);
     52             fa[v][0]=tmp;
     53             que.push(v);
     54         }
     55     }
     56 }
     57 
     58 int LCA(int u,int v)
     59 {
     60     if ( deg[u]>deg[v] ) swap(u,v);
     61     int hu=deg[u],hv=deg[v];
     62     int tu=u,tv=v;
     63     for ( int det=hv-hu,i=0;det;det>>=1,i++ )
     64     {
     65         if ( det&1 ) tv=fa[tv][i];
     66     }
     67     if ( tu==tv ) return tu;
     68     for ( int i=DEG-1;i>=0;i-- )
     69     {
     70         if ( fa[tu][i]==fa[tv][i] ) continue;
     71         tu=fa[tu][i];
     72         tv=fa[tv][i];
     73     }
     74     return fa[tu][0];
     75 }
     76 
     77 int main()
     78 {
     79     int T,u,v,w,m,x,ans;
     80     scanf("%d",&T);
     81     while ( T-- )
     82     {
     83         scanf("%d%d",&n,&m);
     84         init();
     85         memset(flag,false,sizeof(flag));
     86         for ( int i=1;i<n;i++ )
     87         {
     88             scanf("%d%d%d",&u,&v,&w);
     89             addedge(u,v,w);
     90             addedge(v,u,w);
     91             flag[v]=true;
     92         }
     93         int root;
     94         for ( int i=1;i<=n;i++ )
     95         {
     96             if ( !flag[i] )
     97             {
     98                 root=i;
     99                 break;
    100             }
    101         }
    102         BFS(root);
    103         for ( int i=1;i<=m;i++ )
    104         {
    105             scanf("%d%d",&u,&v);
    106             x=LCA(u,v);
    107             ans=d[u]+d[v]-2*d[x];
    108             printf("%d
    ",ans);
    109         }
    110     }
    111     return 0;
    112 }
    HDOJ2586

    2.(HDOJ2874)http://acm.hdu.edu.cn/showproblem.php?pid=2874

    题意:给出一个森林,求给定两点之间的距离

    分析:Tarjan离线算法,有多个根节点,每次询问时判断两个点是否处于同一个树上。LCA传入参数时需要传入当前的点,距离根节点的距离,根节点的编号。但是此题卡内存

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<iostream>
      5 using namespace std;
      6 const int maxn=1e4+10;
      7 const int maxm=1e6+10;
      8 struct Edge{
      9     int to,nxt,w;
     10 }edge[maxn*2];
     11 struct Query{
     12     int q,nxt;
     13     int index;
     14 }query[maxm*2];
     15 int f[maxn],anc[maxn];
     16 int head[maxn],tot;
     17 int ans[maxm],h[maxm],tt,Q,belong[maxn];
     18 int n,d[maxn];
     19 
     20 int find(int x)
     21 {
     22     if ( f[x]==-1 ) return x;
     23     return f[x]=find(f[x]);
     24 }
     25 
     26 void merge(int x,int y)
     27 {
     28     int fx=find(x);
     29     int fy=find(y);
     30     if ( fx!=fy ) f[fx]=fy;
     31 }
     32 
     33 void addedge(int u,int v,int w)
     34 {
     35     edge[tot].to=v;
     36     edge[tot].nxt=head[u];
     37     edge[tot].w=w;
     38     head[u]=tot++;
     39 }
     40 
     41 void addquery(int u,int v,int index)
     42 {
     43     query[tt].q=v;
     44     query[tt].nxt=h[u];
     45     query[tt].index=index;
     46     h[u]=tt++;
     47     query[tt].q=u;
     48     query[tt].nxt=h[v];
     49     query[tt].index=index;
     50     h[v]=tt++;
     51 }
     52 
     53 void init()
     54 {
     55     tot=0;
     56     memset(head,-1,sizeof(head));
     57     tt=0;
     58     memset(h,-1,sizeof(h));
     59     memset(f,-1,sizeof(f));
     60     memset(anc,0,sizeof(anc));
     61 }
     62 
     63 void LCA(int u,int deep,int root)
     64 {
     65     anc[u]=u;
     66     belong[u]=root;
     67     d[u]=deep;
     68     for ( int i=head[u];i!=-1;i=edge[i].nxt )
     69     {
     70         int v=edge[i].to;
     71         int w=edge[i].w;
     72         if ( belong[v]!=-1 ) continue;
     73         LCA(v,deep+w,root);
     74         merge(u,v);
     75         anc[find(u)]=u;
     76     }
     77     for ( int i=h[u];i!=-1;i=query[i].nxt )
     78     {
     79         int v=query[i].q;
     80         if ( belong[v]==root ) 
     81         {
     82             int sum=d[u]+d[v]-2*d[anc[find(v)]];
     83             ans[query[i].index]=sum;
     84         }
     85     }
     86 }
     87 
     88 int main()
     89 {
     90     int u,v,w,k,m,q,x;
     91     while ( scanf("%d%d%d",&n,&m,&Q)!=EOF )
     92     {
     93         init();
     94         for ( int i=1;i<=m;i++ )
     95         {
     96             scanf("%d%d%d",&u,&v,&w);
     97             addedge(u,v,w);
     98             addedge(v,u,w);
     99         }
    100         for ( int i=0;i<Q;i++ )
    101         {
    102             ans[i]=-1;
    103             scanf("%d%d",&u,&v);
    104             addquery(u,v,i);
    105         }
    106         memset(belong,-1,sizeof(belong));
    107         memset(d,-1,sizeof(d));
    108         for ( int i=1;i<=n;i++ )
    109         {
    110             if ( belong[i]==-1 ) LCA(i,0,i);
    111         }
    112         for ( int i=0;i<Q;i++ ) 
    113         {
    114             if ( ans[i]!=-1 ) printf("%d
    ",ans[i]);
    115             else printf("Not connected
    ");    
    116         }
    117     }
    118     return 0;
    119 }
    HDOJ2874(MLE)
      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<vector>
      6 using namespace std;
      7 typedef long long LL;
      8 
      9 const int maxm=2e4+10;
     10 const int maxn=1e4+10;
     11 const int maxq=2e6+10;
     12 struct Node{
     13     int to;
     14     int w;
     15     int next;
     16 }e[maxm];
     17 int eh[maxn],dis[maxn],pre[maxn],etol,vis[maxn];
     18 struct Query{
     19     int to;
     20     int index;
     21     int next;
     22 }qe[maxq];
     23 int qh[maxn],ans[maxq/2],qtol;
     24 int n,m,c;
     25 
     26 void init()
     27 {
     28     etol=qtol=0;
     29     memset(eh,-1,sizeof(eh));
     30     memset(qh,-1,sizeof(qh));
     31 }
     32 
     33 void add1(int u,int v,int w)
     34 {
     35     e[etol].to=v;
     36     e[etol].w=w;
     37     e[etol].next=eh[u];
     38     eh[u]=etol++;
     39 }
     40 
     41 void add2(int u,int v,int id)
     42 {
     43     qe[qtol].index=id;
     44     qe[qtol].to=v;
     45     qe[qtol].next=qh[u];
     46     qh[u]=qtol++;
     47 }
     48 
     49 int Find(int u)
     50 {
     51     if(pre[u]!=u) pre[u]=Find(pre[u]);
     52     return pre[u];
     53 }
     54 
     55 void LCA(int u,int deep,int root)
     56 {
     57     pre[u]=u;
     58     dis[u]=deep;
     59     vis[u]=root;
     60     for(int i=eh[u];~i;i=e[i].next)
     61     {
     62         int v=e[i].to;
     63         if(vis[v]==-1)
     64         {
     65             LCA(v,deep+e[i].w,root);
     66             pre[v]=u;
     67         }
     68     }
     69     for(int i=qh[u];~i;i=qe[i].next)
     70     {
     71         int v=qe[i].to;
     72         if(vis[v]==root)
     73             ans[qe[i].index]=dis[v]+dis[u]-2*dis[Find(v)];
     74     }
     75 }
     76 
     77 
     78 int main()
     79 {
     80     while(~scanf("%d%d%d",&n,&m,&c))
     81     {
     82         int u,v,w;
     83         init();
     84         while(m--)
     85         {
     86             scanf("%d%d%d",&u,&v,&w);
     87             add1(u,v,w);
     88             add1(v,u,w);    
     89         }
     90         for(int i=0;i<c;i++)
     91         {
     92             scanf("%d%d",&u,&v);
     93             ans[i]=-1;
     94             add2(u,v,i);
     95             add2(v,u,i);
     96         }
     97         memset(vis,-1,sizeof(vis));
     98         for(int i=1;i<=n;i++){
     99             if(vis[i]==-1)
    100                 LCA(i,0,i);
    101         }
    102         for(int i=0;i<c;i++)
    103         {
    104             if(ans[i]==-1) puts("Not connected");
    105             else printf("%d
    ",ans[i]);
    106         }
    107     }
    108     return 0;
    109 } 
    HDOJ2874(参考的AC代码)

    3.(HDOJ5044)http://acm.hdu.edu.cn/showproblem.php?pid=5044

    题意:给出一颗树,有m个操作,若为add1 u v w表示从u到v经过点的点权都+w,add2 u v w表示从u到v经过点的边权都+w

    分析:以下解释摘自:https://blog.csdn.net/hongrock/article/details/39616757

    找到U, V的最近公共祖先X。

    add[i][0]表示第i个点的权值。

    des[i]表示第i个点在计算完之后,应该减少的权值。

    add[i][1]表示第i个点跟其父结点之间的边的权值。

    对于操作1有:add[u][0]+=w add[v][0]+=w add[X][0]-=w des[X]+=w;

    对于操作2有:add[u][1]+=w add[v][1]+=w add[X][1]-=2*w

    关于操作的解释:

    对于第一种操作,肯定U到X的路径的结点增加K,V到X的路径也增加K。

    所以我们可以通过将add[U][0]和add[V][0]的信息不断传递上去,直到X为止。

    由于U和V都会传递一个K给X,所以add[X][0]减掉一个K。

    处理完X了,K不能再传给其父节点,所以再用des[X]减掉一次。

    对于第二种操作,同理,也是不断将信息向上传递。但由于这里是边,不会算两次,所以直接在X的位置减掉两倍K即可。

    完成以上后,进行bfs,每次将叶子节点(入度为0的点)不断投入栈中,求出每个点/边的权值

    最后注意下N=1的时候,虽然没有边,但是输出边权还是要留个空行给它。

    注意:此题卡空间卡时间,要输入输出外挂,还要人工手动加栈,初始化要少等等优化

      1 #pragma comment(linker, "/STACK:1024000000,1024000000")  
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 using namespace std;
      7 typedef long long ll;
      8 const int maxn=1e5+10;
      9 const int DEG=20;
     10 struct Edge{
     11     int to,nxt;
     12 }edge[maxn*2];
     13 int head[maxn],tot;
     14 int fa[maxn][DEG]; //fa[i][j]表示节点i的第2^j个祖先 
     15 int deg[maxn];
     16 ll add[maxn][2],node[maxn],edg[maxn],des[maxn];
     17 int du[maxn],tp[maxn];
     18 bool flag[maxn];
     19 
     20 void addedge(int u,int v)
     21 {
     22     edge[tot].to=v;
     23     edge[tot].nxt=head[u];
     24     head[u]=tot++;
     25 }
     26 
     27 void init()
     28 {
     29     tot=0;
     30     memset(head,-1,sizeof(head));
     31 }
     32 
     33 void BFS(int root)
     34 {
     35     queue<int>que;
     36     deg[root]=0;
     37     fa[root][0]=root;
     38     que.push(root);
     39     while ( !que.empty() ) 
     40     {
     41         int tmp=que.front();
     42         que.pop();
     43         for ( int i=1;i<DEG;i++ ) fa[tmp][i]=fa[fa[tmp][i-1]][i-1];
     44         for ( int i=head[tmp];i!=-1;i=edge[i].nxt )
     45         {
     46             int v=edge[i].to;
     47             if ( v==fa[tmp][0] ) continue;
     48             tp[v]=i/2+1;
     49             du[tmp]++;
     50             deg[v]=deg[tmp]+1;
     51             fa[v][0]=tmp;
     52             que.push(v);
     53         }
     54     }
     55 }
     56 
     57 int LCA(int u,int v)
     58 {
     59     if ( deg[u]>deg[v] ) swap(u,v);
     60     int hu=deg[u],hv=deg[v];
     61     int tu=u,tv=v;
     62     for ( int det=hv-hu,i=0;det;det>>=1,i++ )
     63     {
     64         if ( det&1 ) tv=fa[tv][i];
     65     }
     66     if ( tu==tv ) return tu;
     67     for ( int i=DEG-1;i>=0;i-- )
     68     {
     69         if ( fa[tu][i]==fa[tv][i] ) continue;
     70         tu=fa[tu][i];
     71         tv=fa[tv][i];
     72     }
     73     return fa[tu][0];
     74 }
     75 
     76 void bfs(int n)
     77 {
     78     queue<int>que;
     79     for ( int i=1;i<=n;i++ )
     80     {
     81         if ( !du[i] ) que.push(i);
     82     }
     83     while ( !que.empty() )
     84     {
     85         int u=que.front();
     86         que.pop();
     87         node[u]=add[u][0];
     88         add[u][0]-=des[u];
     89         int v=fa[u][0];
     90         add[v][0]+=add[u][0];
     91         add[v][1]+=add[u][1];
     92         edg[tp[u]]+=add[u][1];
     93         if ( !(--du[v]) ) que.push(v);
     94     }
     95 }
     96 
     97 inline bool scan_d(int &num)  
     98 {
     99     char in;bool IsN=false;
    100     in=getchar();
    101     if(in==EOF) return false;
    102     while(in!='-'&&(in<'0'||in>'9')) in=getchar();
    103     if(in=='-'){ IsN=true;num=0;}
    104     else num=in-'0';
    105     while(in=getchar(),in>='0'&&in<='9'){
    106             num*=10,num+=in-'0';
    107     }
    108     if(IsN) num=-num;
    109     return true;
    110 }
    111 
    112 inline void out(long long x) {  
    113     if(x>9) out(x/10);  
    114     putchar(x%10+'0');  
    115 }  
    116 
    117 int main()
    118 {
    119     int T,n,u,v,w,q,h,l;
    120     char op[10];
    121     scan_d(T);
    122     for ( h=1;h<=T;h++ )
    123     {
    124         scan_d(n);
    125         scan_d(q);
    126         init();
    127         for ( int i=1;i<=n;i++ )
    128         {
    129             //flag[i]=false;
    130             add[i][0]=add[i][1]=0;
    131             des[i]=du[i]=node[i]=edg[i]=0;
    132         }
    133         //memset(flag,false,sizeof(flag));
    134         //memset(add,0,sizeof(add));
    135         //memset(des,0,sizeof(des));
    136         //memset(du,0,sizeof(du));
    137         //memset(node,0,sizeof(node));
    138         //memset(edg,0,sizeof(edg));
    139         for ( int i=1;i<n;i++ )
    140         {
    141             scan_d(u);
    142             scan_d(v);
    143             addedge(u,v);
    144             addedge(v,u);
    145         }
    146         int root=1;
    147         /*
    148         for ( int i=1;i<=n;i++ )
    149         {
    150             if ( !flag[i] )
    151             {
    152                 root=i;
    153                 break;
    154             }
    155         }
    156         */
    157         BFS(root);
    158         while ( q-- )
    159         {
    160             scanf("%s",op);
    161             scan_d(u);
    162             scan_d(v);
    163             scan_d(w);
    164             l=LCA(u,v);
    165             if ( op[3]=='1' )
    166             {
    167                 add[u][0]+=w;
    168                 add[v][0]+=w;
    169                 add[l][0]-=w;
    170                 des[l]+=w;
    171             }
    172             else
    173             {
    174                 add[u][1]+=w;
    175                 add[v][1]+=w;
    176                 add[l][1]-=2*w;
    177             }
    178         }
    179         bfs(n);
    180         printf("Case #%d:
    ",h);
    181         for ( int i=1;i<=n;i++ ) 
    182         {
    183             out(node[i]);
    184             if ( i!=n ) printf(" ");
    185             else printf("
    ");
    186         }
    187         for ( int i=1;i<n;i++ )
    188         {
    189             out(edg[i]);
    190             if ( i!=(n-1) ) printf(" ");
    191             else printf("
    ");
    192         }
    193         if ( n==1 ) printf("
    ");
    194     }
    195     return 0;
    196 }
    HDOJ5044(TLE)

    4.(HDOJ4547)http://acm.hdu.edu.cn/showproblem.php?pid=4547

    分析:从节点a出发,a到任意一个子节点只需要1步,a到任意一个父节点为两个点的距离差。所以询问给出u,v时,先求出l=lca(u,v),ans=dis[u]-dis[l],如果v于l不是同一个点则ans++(从l一步到达v)

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<map>
      6 #include<string>
      7 #include<iostream>
      8 using namespace std;
      9 const int maxn=1e5+10;
     10 const int DEG=20;
     11 struct Edge{
     12     int to,nxt,w;
     13 }edge[maxn*2];
     14 int head[maxn],tot;
     15 int fa[maxn][DEG]; //fa[i][j]表示节点i的第2^j个祖先 
     16 int deg[maxn];
     17 bool flag[maxn];
     18 int dis[maxn];
     19 map<string,int>mp;
     20 
     21 void addedge(int u,int v,int w)
     22 {
     23     edge[tot].to=v;
     24     edge[tot].nxt=head[u];
     25     edge[tot].w=w;
     26     head[u]=tot++;
     27 }
     28 
     29 void init()
     30 {
     31     tot=0;
     32     memset(head,-1,sizeof(head));
     33 }
     34 
     35 void BFS(int root)
     36 {
     37     queue<int>que;
     38     deg[root]=0;
     39     fa[root][0]=root;
     40     que.push(root);
     41     while ( !que.empty() ) 
     42     {
     43         int tmp=que.front();
     44         que.pop();
     45         for ( int i=1;i<DEG;i++ ) fa[tmp][i]=fa[fa[tmp][i-1]][i-1];
     46         for ( int i=head[tmp];i!=-1;i=edge[i].nxt )
     47         {
     48             int v=edge[i].to;
     49             int w=edge[i].w;
     50             if ( v==fa[tmp][0] ) continue;
     51             dis[v]=dis[tmp]+w;
     52             deg[v]=deg[tmp]+1;
     53             fa[v][0]=tmp;
     54             que.push(v);
     55         }
     56     }
     57 }
     58 
     59 int LCA(int u,int v)
     60 {
     61     if ( deg[u]>deg[v] ) swap(u,v);
     62     int hu=deg[u],hv=deg[v];
     63     int tu=u,tv=v;
     64     for ( int det=hv-hu,i=0;det;det>>=1,i++ )
     65     {
     66         if ( det&1 ) tv=fa[tv][i];
     67     }
     68     if ( tu==tv ) return tu;
     69     for ( int i=DEG-1;i>=0;i-- )
     70     {
     71         if ( fa[tu][i]==fa[tv][i] ) continue;
     72         tu=fa[tu][i];
     73         tv=fa[tv][i];
     74     }
     75     return fa[tu][0];
     76 }
     77 
     78 int main()
     79 {
     80     int T,n,q,u,v,w,num,l,ans;
     81     string s1,s2;
     82     scanf("%d",&T);
     83     while ( T-- )
     84     {
     85         scanf("%d%d",&n,&q);
     86         mp.clear();
     87         init();
     88         num=0;
     89         memset(flag,false,sizeof(flag));
     90         memset(dis,0,sizeof(dis));
     91         for ( int i=1;i<n;i++ )
     92         {
     93             cin>>s1>>s2;
     94             if ( !mp[s1] ) mp[s1]=++num;
     95             if ( !mp[s2] ) mp[s2]=++num;
     96             v=mp[s1];
     97             u=mp[s2];
     98             addedge(u,v,1);
     99             flag[v]=true;
    100         }
    101         int root;
    102         for ( int i=1;i<=n;i++ )
    103         {
    104             if ( !flag[i] )
    105             {
    106                 root=i;
    107                 break;
    108             }
    109         }
    110         BFS(root);
    111         while ( q-- )
    112         {
    113             cin>>s1>>s2;
    114             u=mp[s1];
    115             v=mp[s2];
    116             l=LCA(u,v);
    117             ans=dis[u]-dis[l];
    118             if ( l!=v ) ans++;
    119             printf("%d
    ",ans);
    120         }
    121     }
    122     return 0;
    123 }
    HDOJ4547

    5.(HDOJ5274)http://acm.hdu.edu.cn/showproblem.php?pid=5274

    题意:有一颗树,有n个点,每个点都有个点权。现在有q个询问,总共有两种操作
    0 x y代表把编号为x点的权值变成y

    1 x y求出点x到点y的路径上出现点权值为奇数的点,若都为偶数则输出-1。题目保证最多只有一个为奇数的点权值

    分析:官方题解:

    题目里有一个很神奇的性质:路径上最多只有一个数出现奇数次。

    这应该马上想到异或。因为异或两次和没异或是等价的。此外异或满足区间减性质。

    因为有修改,我们很自然地想到用数据结构维护。

    最无脑的就是直接上树链剖分或是Splay维护区间xor值即可。

    仔细想一想,发现可以利用LCA消去“树上路径”,转化为根到x路径上求xor值。

    我们可以很经典地直接使用线段树或树状数组维护dfs序。 

    有一个很强的trick就是权值可以为0!

    所以比如路径上有3个0,虽然他们xor值还是0,但是他们是出现了奇数次。

    我特意把A[i]说成∈自然数集而不是[0,100000][0,100000][0,100000],就是想尽量不被发现。

    怎么避免呢?单独维护0的情况?

    有一个很简单的解决方案:直接把读入时所有权值+1,输出的时候再-1即可!

    时间复杂度为O(N∗log(N)2)或者O(N∗log(N))

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 const int maxn=1e5+10;
      6 int rmq[maxn*2]; 
      7 struct ST
      8 {
      9     int mm[2*maxn];
     10     int dp[2*maxn][20];
     11     void init(int n)
     12     {
     13         mm[0]=-1;
     14         for ( int i=1;i<=n;i++ )
     15         {
     16             mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
     17             dp[i][0]=i;
     18         }
     19         for ( int j=1;j<=mm[n];j++ )
     20         {
     21             for ( int i=1;i+(1<<j)-1<=n;i++ ) 
     22             {
     23                 if ( rmq[dp[i][j-1]]<rmq[dp[i+(1<<(j-1))][j-1]] ) dp[i][j]=dp[i][j-1];
     24                 else dp[i][j]=dp[i+(1<<(j-1))][j-1];    
     25             }
     26         }
     27     } 
     28     int query(int a,int b) 
     29     {
     30         if ( a>b ) swap(a,b);
     31         int k=mm[b-a+1];
     32         if ( rmq[dp[a][k]]<=rmq[dp[b-(1<<k)+1][k]] ) return dp[a][k];
     33         else return dp[b-(1<<k)][k];
     34     }
     35 };
     36 struct Edge{
     37     int to,nxt;
     38 }edge[maxn*2];
     39 int tot,head[maxn],in[maxn],out[maxn];
     40 int F[maxn],P[maxn],cnt,now,val[maxn]; 
     41 int bit[maxn*2];
     42 ST st;
     43 
     44 int lowbit(int x)
     45 {
     46     return x&(-x);
     47 }
     48 
     49 void add(int k,int num)
     50 {
     51     while ( k<maxn*2 )
     52     {
     53         bit[k]^=num;
     54         k+=lowbit(k);
     55     }
     56 }
     57 
     58 int sum(int k)
     59 {
     60     int s=0;
     61     while ( k )
     62     {
     63         s^=bit[k];
     64         k-=lowbit(k);
     65     }
     66     return s;
     67 }
     68 
     69 void init()
     70 {
     71     tot=0;
     72     memset(head,-1,sizeof(head));
     73 }
     74 
     75 void addedge(int u,int v) 
     76 {
     77     edge[tot].to=v;
     78     edge[tot].nxt=head[u];
     79     head[u]=tot++;
     80 }
     81 
     82 void dfs(int u,int pre,int dep)
     83 {
     84     F[++cnt]=u;
     85     in[u]=++now;
     86     rmq[cnt]=dep;
     87     P[u]=cnt;
     88     for ( int i=head[u];i!=-1;i=edge[i].nxt )
     89     {
     90         int v=edge[i].to;
     91         if ( v==pre ) continue;
     92         dfs(v,u,dep+1);
     93         F[++cnt]=u;
     94         rmq[cnt]=dep;
     95     }
     96     out[u]=++now;
     97 }
     98 
     99 void LCA_init(int root,int num) 
    100 {
    101     cnt=0;
    102     now=0;
    103     dfs(root,root,0);
    104     st.init(2*num-1);
    105 }
    106 
    107 int query(int u,int v) 
    108 {
    109     return F[st.query(P[u],P[v])];
    110 }
    111 bool flag[maxn];
    112 
    113 int main()
    114 {
    115     int T,u,v,q,op,N;
    116     scanf("%d",&T);
    117     while ( T-- )
    118     {
    119         scanf("%d%d",&N,&q);
    120         init();
    121         memset(flag,false,sizeof(flag));
    122         memset(bit,0,sizeof(bit));
    123         for ( int i=1;i<N;i++ )
    124         {
    125             scanf("%d%d",&u,&v);
    126             addedge(u,v);
    127             addedge(v,u);
    128             flag[v]=true;
    129         }
    130         int root;
    131         for ( int i=1;i<=N;i++ )
    132         {
    133             if ( !flag[i] ) 
    134             {
    135                 root=i;
    136                 break;
    137             }
    138         }
    139         LCA_init(root,N);
    140         for ( int i=1;i<=N;i++ ) 
    141         {
    142             scanf("%d",&val[i]);
    143             val[i]++;
    144             add(in[i],val[i]);
    145             add(out[i],val[i]);
    146         }
    147         //for ( int i=1;i<=N;i++ ) printf("%d %d
    ",in[i],out[i]);
    148         //for ( int i=1;i<=2*N;i++ ) printf("%d
    ",sum(i));
    149         while ( q-- )
    150         {
    151             scanf("%d%d%d",&op,&u,&v);
    152             if ( op==0 )
    153             {
    154                 v++;
    155                 add(in[u],val[u]^v);
    156                 add(out[u],val[u]^v);
    157                 val[u]=v;
    158             }
    159             else
    160             {
    161                 int l=query(u,v);
    162                 int ans=sum(in[u])^sum(in[v])^val[l];
    163                 if ( ans==0 ) printf("-1
    ");
    164                 else printf("%d
    ",ans-1);
    165             }    
    166         }
    167         //for ( int i=1;i<=N;i++ ) printf("%d %d
    ",in[i],out[i]);
    168         //for ( int i=1;i<=2*N;i++ ) printf("%d
    ",sum(i));
    169     }
    170     return 0;
    171 }
    HDOJ5274(WA)
     1 #pragma comment(linker, "/STACK:102400000,102400000")
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<algorithm>
     7 using namespace std;
     8 #define MAXN 100005
     9 #define MAXM 300005
    10 #define LOG 19
    11 #define lowbit(i) (i & -i)
    12 vector<int>vec[MAXN];
    13 int _,n,q,cnt;
    14 int val[MAXN],uid[MAXN],vid[MAXN],dp[LOG][MAXM],pre[MAXM];
    15 void modify(int i,int v)
    16 {
    17     for(;i < MAXM;i += lowbit(i))
    18         pre[i] ^= v;
    19 }
    20 int sum(int i)
    21 {
    22     int ans = 0;
    23     for(;i;i -= lowbit(i))
    24         ans ^= pre[i];
    25     return ans;
    26 }
    27 void dfs(int u,int fa)
    28 {
    29     for(int i = 0;i < vec[u].size();i++)
    30     {
    31         int v = vec[u][i];
    32         if(v == fa)continue;
    33         uid[v] = ++cnt;
    34         modify(cnt,val[v]);
    35         dp[0][cnt] = v;
    36         dfs(v,u);
    37         vid[v] = ++cnt;
    38         modify(cnt,val[v]);
    39         dp[0][cnt] = u;
    40     }
    41 }
    42 void init_rmq()
    43 {
    44     for(int i = 1;(1 << i) <= cnt;i++)
    45         for(int j = 1;j + (1 << i) - 1 <= cnt;j++)
    46             dp[i][j] = min(dp[i - 1][j],dp[i - 1][j + (1 << i - 1)]);
    47 }
    48 int lca(int l,int r)
    49 {
    50     if(l > r)swap(l,r);
    51     int i = 0;
    52     for(;l + (1 << i) - 1 <= r;i++);
    53     i--;
    54     return min(dp[i][l],dp[i][r - (1 << i) + 1]);
    55 }
    56 int main()
    57 {
    58     scanf("%d",&_);
    59     while(_--)
    60     {
    61         scanf("%d%d",&n,&q);
    62         for(int i = 0;i <= n;i++)vec[i].clear();
    63         vec[0].push_back(1) , vec[1].push_back(0);
    64         memset(pre,0,sizeof(pre));
    65         for(int i = 1;i < n;i++)
    66         {
    67             int u,v;
    68             scanf("%d%d",&u,&v);
    69             vec[u].push_back(v),vec[v].push_back(u);
    70         }
    71         for(int i = 1;i <= n;i++)
    72         {
    73             scanf("%d",&val[i]);
    74             val[i]++;
    75         }
    76         cnt = 0;
    77         dfs(0,-1);
    78         init_rmq();
    79         for(int i = 0;i < q;i++)
    80         {
    81             int c,u,v;
    82             scanf("%d%d%d",&c,&u,&v);
    83             if(c == 0)
    84             {
    85                 v++;
    86                 modify(uid[u],val[u] ^ v);
    87                 modify(vid[u],val[u] ^ v);
    88                 val[u] = v;
    89             }
    90             else
    91             {
    92                 int fa = lca(uid[u],uid[v]);
    93                 int ans = sum(uid[u]) ^ sum(uid[v]) ^ val[fa];
    94                 if(!ans)puts("-1");
    95                 else printf("%d
    ",ans - 1);
    96             }
    97         }
    98     }
    99 }
    HDOJ5274(参考的AC代码)

    6.(POJ2763)http://poj.org/problem?id=2763

    题意:有一颗树,每条边都有自己的边权,起点在s,有q个询问,询问总共有两种操作

    A:从当前点移动到x,输出所需要的时间  B:将通过边x的时间改为t

    分析:利用RMQ计算LCA所用的,按DFS访问的顺序排列的顶点顺序。这样u到v之间的路径就是在序列中u和v之间的所有边减去往返重复的部分得到的结果。只要令沿叶子方向的边权为正,沿根方向的部分为负,于是有d(u,v)=d(LCA(u,v),u)+d(LCA(u,v),v)可以用bit进行计算

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 typedef long long ll;
      6 const int maxn=1e5+10;
      7 int rmq[maxn*2];  
      8 struct ST
      9 {
     10     int mm[2*maxn];
     11     int dp[2*maxn][20];
     12     void init(int n)
     13     {
     14         mm[0] = -1;
     15         for(int i = 1;i <= n;i++)
     16         {
     17             mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
     18             dp[i][0] = i;
     19         }
     20         for(int j = 1; j <= mm[n];j++)
     21             for(int i = 1; i + (1<<j) - 1 <= n; i++)
     22                 dp[i][j] = rmq[dp[i][j-1]] < rmq[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
     23     }
     24     int query(int a,int b)
     25     {
     26         if(a > b)swap(a,b);
     27         int k = mm[b-a+1];
     28         return rmq[dp[a][k]] <= rmq[dp[b-(1<<k)+1][k]]?dp[a][k]:dp[b-(1<<k)+1][k];
     29     }
     30 };
     31 
     32 struct Edge{
     33     int to,nxt,w;
     34 }edge[maxn*2];
     35 int tot,head[maxn];
     36 int F[maxn],P[maxn],cnt,n,es[maxn*2]; 
     37 ll bit[maxn*2];
     38 ST st;
     39 
     40 void init()
     41 {
     42     tot=0;
     43     memset(head,-1,sizeof(head));
     44     memset(bit,0,sizeof(bit));
     45 }
     46 
     47 int lowbit(int x)
     48 {
     49     return x&(-x);
     50 }
     51 
     52 void add(int k,int num)
     53 {
     54     while ( k<=n )
     55     {
     56         bit[k]+=num;
     57         k+=lowbit(k);
     58     }
     59 }
     60 
     61 ll sum(int k)
     62 {
     63     ll sum_=0;
     64     while ( k )
     65     {
     66         sum_+=bit[k];
     67         k-=lowbit(k);
     68     }
     69     return sum_;
     70 }
     71 
     72 void addedge(int u,int v,int w) 
     73 {
     74     edge[tot].to=v;
     75     edge[tot].nxt=head[u];
     76     edge[tot].w=w;
     77     head[u]=tot++;
     78 }
     79 
     80 void dfs(int u,int pre,int dep)
     81 {
     82     F[++cnt]=u;
     83     rmq[cnt]=dep;
     84     P[u]=cnt;
     85     for ( int i=head[u];i!=-1;i=edge[i].nxt )
     86     {
     87         int v=edge[i].to;
     88         int w=edge[i].w;
     89         if ( v==pre ) continue;
     90         es[i]=cnt+1;
     91         add(es[i],w);
     92         dfs(v,u,dep+1);
     93         F[++cnt]=u;
     94         es[i^1]=cnt;
     95         add(es[i^1],-w);
     96         rmq[cnt]=dep;
     97     }
     98 }
     99 
    100 void LCA_init(int root,int num) 
    101 {
    102     cnt=0;
    103     dfs(root,root,0);
    104     st.init(2*num-1);
    105 }
    106 
    107 int query(int u,int v) 
    108 {
    109     return F[st.query(P[u],P[v])];
    110 }
    111 bool flag[maxn];
    112 
    113 int main()
    114 {
    115     int T,N,q,s,u,v,w,op;
    116     while ( scanf("%d%d%d",&N,&q,&s)!=EOF )
    117     {
    118         init();
    119         n=2*N-1;
    120         memset(flag,false,sizeof(flag));
    121         for ( int i=1;i<N;i++ )
    122         {
    123             scanf("%d%d%d",&u,&v,&w);
    124             addedge(u,v,w);
    125             addedge(v,u,w);
    126             flag[v]=true;
    127         }
    128         int root;
    129         for ( int i=1;i<=N;i++ )
    130         {
    131             if ( !flag[i] ) 
    132             {
    133                 root=i;
    134                 break;
    135             }
    136         }
    137         LCA_init(root,N);
    138         u=s;
    139         //for ( int i=1;i<=n;i++ ) printf("%lld
    ",sum(i));
    140         //for ( int i=0;i<2*(N-1);i++ ) printf("%d
    ",es[i]);
    141         while ( q-- )
    142         {
    143             scanf("%d",&op);
    144             if ( op==0 )
    145             {
    146                 scanf("%d",&v);
    147                 int l=query(u,v);
    148                 printf("%lld
    ",sum(P[u])+sum(P[v])-2*sum(P[l]));
    149                 u=v;
    150             }
    151             else 
    152             {
    153                 int p,x,k1,k2;
    154                 scanf("%d%d",&p,&x);
    155                 k1=es[(p-1)*2];
    156                 k2=es[((p-1)*2)^1];
    157                 add(k1,x-edge[(p-1)*2].w);
    158                 add(k2,edge[((p-1)*2)^1].w-x);
    159                 edge[(p-1)*2].w=edge[((p-1)*2)^1].w=x;
    160             }
    161         }
    162         //for ( int i=1;i<=n;i++ ) printf("%lld
    ",sum(i));
    163     }
    164     return 0;
    165 }
    POJ2763(WA)

    注:以上两题通过与标程对拍也没找到错误的点,希望有人可以提供一下有用的数据,谢谢!

  • 相关阅读:
    linux中解压.tgz, .tar.gz ,zip ,gz, .tar文件
    hook(v16.7测试)?
    React优点?
    Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?
    说说数据库连接池工作原理和实现方案?
    short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
    Oracle的数据优化(经常被问到)?
    存储过程和函数的区别?
    Collection 和 Collections的区别?
    说说数据库连接池工作原理和实现方案?
  • 原文地址:https://www.cnblogs.com/HDUjackyan/p/9102171.html
Copyright © 2020-2023  润新知