zoukankan      html  css  js  c++  java
  • Codeforces Round #614 选讲

    http://codeforces.com/contest/1292/problem/C

    注意到编号x的边对答案要有贡献,必须和0到x-1的边一起形成一条链,否则x及编号比x大的边都没有贡献。由此,对答案有贡献的边形成了一条链,且这条链的编号是个谷形,即中间编号小,往两边编号变大,编号最大的边在最外侧。由此可以进行dp,dp[u][v]表示如果上述链为点u到点v这条链的答案。令sz[u][v]为以u为根,子树v的大小;fa[u][v]为以u为根,点v的父亲,则有dp[u][v]=dp[v][u]=sz[u][v]*sz[v][u]+max(dp[u][fa[u][v]],dp[v][fa[v][u]])。(考虑放入编号最大的一条边,相当于某些路径的mex增加了1)

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 
     5 int n;
     6 #define maxn 3011
     7 struct Edge{int to,next;}edge[maxn<<1]; int first[maxn],le=2;
     8 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
     9 void insert(int x,int y) {in(x,y); in(y,x);}
    10 
    11 int sz[maxn][maxn],fa[maxn][maxn];
    12 LL dp[maxn][maxn]; 
    13 struct NODE{int x,y;};
    14 vector<NODE> vec[maxn];
    15 void dfs(int x,int f,int top,int dep)
    16 {
    17     sz[top][x]=1; fa[top][x]=f;
    18     if (dep>0) vec[dep].push_back((NODE){top,x});
    19     for (int i=first[x];i;i=edge[i].next)
    20     {
    21         Edge &e=edge[i]; if (e.to==f) continue;
    22         dfs(e.to,x,top,dep+1); sz[top][x]+=sz[top][e.to];
    23     }
    24 }
    25 
    26 int main()
    27 {
    28     scanf("%d",&n);
    29     for (int i=1,x,y;i<n;i++) {scanf("%d%d",&x,&y); insert(x,y);}
    30     for (int i=1;i<=n;i++) dfs(i,0,i,0);
    31     
    32     for (int len=1;len<n;len++)
    33         for (int i=0,to=vec[len].size();i<to;i++)
    34         {
    35             int a=vec[len][i].x,b=vec[len][i].y;
    36             dp[a][b]=dp[b][a]=sz[a][b]*sz[b][a]+max(dp[a][fa[a][b]],dp[b][fa[b][a]]);
    37         }
    38     
    39     LL ans=0;
    40     for (int i=1;i<=n;i++)
    41         for (int j=1;j<=n;j++)
    42             ans=max(ans,dp[i][j]);
    43     printf("%lld
    ",ans);
    44     return 0;
    45 }
    View Code

     http://codeforces.com/contest/1292/problem/D

    回忆找重心的过程:从根节点开始,看点权和最大的子树,其点权和是否超过总的一半,是则在该子树中找重心,否则当前点为重心。以1为根时,在深度dep的节点x的子树中的点y必须满足:y的质因子中最大的dep个乘积即为x。由此,从1出发,对所有数进行分解后(相同的合并),每次取每个数的最大的质因子p,算出每个p的点权和,然后看重儿子的点权和是否超过n/2,若否则找到答案,若是则调整答案,并删去该子树中的最大质因子(将其次数-1),然后在该子树中循环进行该过程。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 
     5 int n;
     6 #define maxn 5011
     7 #define MAXNUM 5000
     8 int cnt[maxn],fra[maxn][maxn],poi[maxn],cntpri[maxn],pri[maxn],lp; bool vis[maxn];
     9 void makeprime(int n)
    10 {
    11     for (int i=2;i<=n;i++)
    12     {
    13         if (!vis[i]) pri[++lp]=i;
    14         for (int j=1;j<=lp && 1ll*i*pri[j]<=n;j++)
    15         {
    16             vis[i*pri[j]]=1;
    17             if (i%pri[j]==0) break;
    18         }
    19     }
    20 }
    21 
    22 int main()
    23 {
    24     scanf("%d",&n);
    25     for (int i=1,x;i<=n;i++) scanf("%d",&x),cnt[x]++;
    26     makeprime(MAXNUM);
    27     
    28     LL ans=0;
    29     for (int x=0;x<=MAXNUM;x++)
    30         for (int i=1;i<=lp && pri[i]<=x;i++)
    31         {
    32             for (int j=pri[i];j<=x;j*=pri[i])
    33                 fra[x][i]+=x/j;
    34             ans+=1ll*cnt[x]*fra[x][i];
    35         }
    36         //trick: The number of prime 2 in k! is k/2+k/4+k/8+...
    37     
    38     for (int x=0;x<=MAXNUM;x++) poi[x]=lp;
    39     while (1)
    40     {
    41         for (int i=1;i<=lp;i++) cntpri[i]=0;
    42         for (int x=0;x<=MAXNUM;x++)
    43         {
    44             while (poi[x]>0 && fra[x][poi[x]]==0) poi[x]--;
    45             if (poi[x]>0) cntpri[poi[x]]+=cnt[x];
    46         }
    47         bool findans=1;
    48         for (int i=1;i<=lp;i++) if (cntpri[i]*2>n)
    49         {
    50             findans=0;
    51             ans-=cntpri[i]-(n-cntpri[i]);
    52             for (int x=0;x<=MAXNUM;x++) if (poi[x]>0 && poi[x]==i) fra[x][poi[x]]--; else poi[x]=0;
    53             break;
    54         }
    55         if (findans) break;
    56     }
    57     printf("%lld
    ",ans);
    58     return 0;
    59 }
    View Code

  • 相关阅读:
    jq 换图片路径
    sql 把一列的数据按逗号分隔转换成多行
    sql 数据库查看主外键关联
    sql 表连接 join
    sql 查看 锁定的表 或者 未提交 的事务
    WMI技术介绍和应用——查询硬件信息
    System.Web.HttpContext.Current.Server.MapPath("~/upload/SH") 未将对象引用设置为实例对象
    sql server output用法说明
    merge into 的用法
    JAVA Stop The World 第八节
  • 原文地址:https://www.cnblogs.com/Blue233333/p/12239920.html
Copyright © 2011-2022 走看看