VK Cup 2017

来源:互联网 发布:windows如何打开war包 编辑:程序博客网 时间:2024/04/26 01:02

感觉自己代码能力太差了,这场比赛的题都调得很痛苦。。

C. Bear and Tree Jumps

  对于一棵有根树来说,dfs可以得到每个节点到树根的距离。注意到跳跃距离最大为5,我们可以把距离最多分为五类,同样地,dfs出所有节点到根的距离信息。
  我的解法分为两次dfs。第一次dfs可以得到节点1为树根时的距离信息。第二次dfs的目的是“换根”,也就是让每个节点以dfs序作为树根,统计与当前根节点有关的所有pair的总距离。

#include <bits/stdc++.h>using namespace std;#define ll long longconst int maxn = 200010;vector<int> E[maxn];ll dis[maxn][5];int p[maxn];ll n,k;ll ans[maxn];ll res = 0;void dfs1(int u,int pre){    dis[u][0] = 1;    int len = E[u].size();    for(int i=0;i<len;i++){        int v = E[u][i];        if(v==pre)continue;        p[v] = u;        dfs1(v,u);        ans[u] += dis[v][0]-1;        ans[u] += ans[v];        for(int i=0;i<k;i++){            dis[u][i] += dis[v][(i+k-1)%k];        }    }}void dfs2(int u,int pre){    int len = E[u].size();    ll tmp = ans[u];    if(u!=1)ans[u] += ans[p[u]] + dis[p[u]][0]-1;    res += ans[u];    for(int i=0;i<len;i++){        int v = E[u][i];        if(v==pre)continue;        ans[u] -= dis[v][0]-1;        ans[u] -= ans[v];        for(int i=0;i<k;i++){            dis[u][i] -= dis[v][(i+k-1)%k];        }        for(int i=0;i<k;i++){            dis[v][i] += dis[u][(i+k-1)%k];        }        dfs2(v,u);        for(int i=k-1;i>=0;i--){            dis[v][i] -= dis[u][(i+k-1)%k];        }        for(int i=k-1;i>=0;i--){            dis[u][i] += dis[v][(i+k-1)%k];        }        ans[u] += ans[v];        ans[u] += dis[v][0]-1;    }    ans[u] = tmp;}int main(){    cin>>n>>k;    for(int i=1;i<n;i++){        int u,v;        scanf("%d %d",&u,&v);        E[u].push_back(v);        E[v].push_back(u);    }    dfs1(1,0);    dfs2(1,0);    res += n*(n-1);    cout<<res/2<<endl;    return 0;}

D. Bear and Company

  做这题的时候,如果只提示我是dp的话,我也会往区间分割方面想,之前没写过这种类型的dp,确实比较巧妙。因为每个位置的字符都可以往任意地方跑,于是分区间是不管用的。
  容易发现除了VK以外的字符都是等效的,定义状态dp(i,j,k)表示组成前i+j+k个字符有i个’V’,j个’K’和k个其他字符需要的最小次数,再加一维表示最后一个字符是否是’V’。然后枚举添加三种类型的字符。

#include <bits/stdc++.h>using namespace std;#define ll long longconst int maxn = 200010;vector<int> E[maxn];ll dis[maxn][5];int p[maxn];ll n,k;ll ans[maxn];ll res = 0;void dfs1(int u,int pre){    dis[u][0] = 1;    int len = E[u].size();    for(int i=0;i<len;i++){        int v = E[u][i];        if(v==pre)continue;        p[v] = u;        dfs1(v,u);        ans[u] += dis[v][0]-1;        ans[u] += ans[v];        for(int i=0;i<k;i++){            dis[u][i] += dis[v][(i+k-1)%k];        }    }}void dfs2(int u,int pre){    int len = E[u].size();    ll tmp = ans[u];    if(u!=1)ans[u] += ans[p[u]] + dis[p[u]][0]-1;    res += ans[u];    for(int i=0;i<len;i++){        int v = E[u][i];        if(v==pre)continue;        ans[u] -= dis[v][0]-1;        ans[u] -= ans[v];        for(int i=0;i<k;i++){            dis[u][i] -= dis[v][(i+k-1)%k];        }        for(int i=0;i<k;i++){            dis[v][i] += dis[u][(i+k-1)%k];        }        dfs2(v,u);        for(int i=k-1;i>=0;i--){            dis[v][i] -= dis[u][(i+k-1)%k];        }        for(int i=k-1;i>=0;i--){            dis[u][i] += dis[v][(i+k-1)%k];        }        ans[u] += ans[v];        ans[u] += dis[v][0]-1;    }    ans[u] = tmp;}int main(){    cin>>n>>k;    for(int i=1;i<n;i++){        int u,v;        scanf("%d %d",&u,&v);        E[u].push_back(v);        E[v].push_back(u);    }    dfs1(1,0);    dfs2(1,0);    res += n*(n-1);    cout<<res/2<<endl;    return 0;}
0 0
原创粉丝点击