Codeforces VK Cup 2015 - Round 2 (unofficial online mirror, Div. 1 only)

2015-04-18 14:47:35

总结:难度没有顺序的一场... 打得我毫无脾气... 认清了自己的实力。

  接下来要调整了下状态了... 静下心,提高效率,老老实实地去攻克专题和训练赛。

  比赛仅做了两题,E和C... 然后一直在做B题,wa7,最后虽然知道如何错,但已经来不及改了。

  

B题

  比赛时死活都用一维的dp来搞... 后来发现自己too young,半夜时脑子转不过来,也不愿意换算法了...

  正解是树形DP,用dp[i][1 / 0]来记录以 i 号节点为根的子树中取奇数 / 偶数个点能构成的最大合法解。

  由于点有序,我们从最后一个点 n 开始倒序考虑:

    对于第 i 号节点,我们要根据其子节点的dp[son][1 / 0]来计算dp[i][1 / 0]

    实际上我们要在这一层再来一个DP,DP[i][0 / 1]表示考虑前 i 个儿子取奇数 / 偶数个节点能构成的最大值。

    那么就有 dp[i][0] = DP[num of son][0]

        dp[i][1] = max(DP[num of son][1] , dp[i][0] + a[i]](算dp[i][1]还要考虑加上dp[i][0]加上根节点本身)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=0;i<(n);++i)
17 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
18 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
19 #define MP(a,b) make_pair(a,b)
20 
21 typedef long long ll;
22 typedef pair<int,int> pii;
23 const int INF = (1 << 30) - 1;
24 const int MAXN = 200010;
25 
26 int n;
27 int A[MAXN];
28 ll dp[MAXN][2],DP[MAXN][2];
29 vector<int> g[MAXN];
30 
31 int main(){
32     int a;
33     scanf("%d",&n);
34     FOR(i,1,n){
35         scanf("%d%d",&a,&A[i]);
36         if(a != -1) g[a].push_back(i);
37     }
38     for(int i = n; i >= 1; --i){
39         int sz = g[i].size();
40         DP[0][0] = 0;
41         DP[0][1] = -INF;
42         for(int j = 0; j < sz; ++j){
43             int v = g[i][j];
44             DP[j + 1][0] = max(DP[j][0] + dp[v][0],DP[j][1] + dp[v][1]);
45             DP[j + 1][1] = max(DP[j][0] + dp[v][1],DP[j][1] + dp[v][0]);
46         }
47         dp[i][0] = DP[sz][0];
48         dp[i][1] = max(DP[sz][1],dp[i][0] + A[i]);
49     }
50     cout << max(dp[1][0],dp[1][1]) << endl;
51     return 0;
52 }
View Code

 

C题

  数学题。

  P先走,V后走。首先计算P的最小步数:xp+yp,V的最小步数:max(xv,yv)。

  显然,如果P的最小步数小于V的最小步数,那么P赢(因为V是挡不住P的)

  否则,我们需要考虑两种情况:

    (1)P能挡住V

      我们发现只要P能在某个时刻挡住V的对角线方向,接着P就跟着V平行移动,那么P就赢。

      那么只要P能比V先到达其对角线上某点就是P赢。可以用(xp <= xv && yp <= yv)判断

    (2)P挡不住V,此时P的最小步数较大,V赢

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <vector>
 5 #include <map>
 6 #include <set>
 7 #include <stack>
 8 #include <queue>
 9 #include <string>
10 #include <iostream>
11 #include <algorithm>
12 using namespace std;
13 
14 #define MEM(a,b) memset(a,b,sizeof(a))
15 #define REP(i,n) for(int i=0;i<(n);++i)
16 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
17 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
18 #define MP(a,b) make_pair(a,b)
19 
20 typedef long long ll;
21 typedef pair<int,int> pii;
22 const int INF = (1 << 30) - 1;
23 
24 int x1,y1,x2,y2;
25 
26 int main(){
27     scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
28     int A = x1 + y1;
29     int B = max(x2,y2);
30     if(A <= B || (x1 <= x2 && y1 <= y2)) printf("Polycarp\n");
31     else printf("Vasiliy\n");
32     return 0;
33 }
View Code

 

E题

  一开始就做的这题... 第一次打的分类讨论... 后来精简了一下思路就过了。

  找到第一个不匹配点 st 和最后一个不匹配点 ed,那么我们只要考虑两段串的 s[st ~ ed] 部分。

  因为这两段的头尾均不匹配,所以肯定要在头 / 尾上加一个字符构成大串。

  那么只要把 s1[st~ed] 向左移一位,看 s1[st+1 ~ ed] 与 s2[st ~ ed -1] 是否匹配,

      把 s1[st~ed] 向右移一位,看 s1[st ~ ed - 1] 与 s2[st+1 ~ ed] 是否匹配。

  答案就是匹配的次数。不需要考虑其他情况。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=0;i<(n);++i)
17 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
18 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
19 #define MP(a,b) make_pair(a,b)
20 
21 typedef long long ll;
22 typedef pair<int,int> pii;
23 const int INF = (1 << 30) - 1;
24 const int MAXN = 100010;
25 
26 int n;
27 char s1[MAXN],s2[MAXN];
28 int vis[MAXN];
29 
30 int main(){
31     scanf("%d",&n);
32     scanf("%s",s1 + 1);
33     scanf("%s",s2 + 1);
34     for(int i = 1; i <= n; ++i) if(s1[i] != s2[i]) vis[i] = 1;
35     int st = -1,ed;
36     for(int i = 1; i <= n; ++i) if(vis[i]){
37         if(st == -1) st = i;
38         ed = i;
39     }
40     int ans = 0;
41     bool flag = true;
42     for(int i = st; i <= ed - 1; ++i) if(s1[i] != s2[i + 1]) flag = false;
43     if(flag) ans++;
44     flag = true;
45     for(int i = st + 1; i <= ed; ++i) if(s1[i] != s2[i - 1]) flag = false;
46     if(flag) ans++;
47     printf("%d\n",ans);
48     return 0;
49 }
View Code

 

posted @ 2015-04-18 15:25  Naturain  阅读(121)  评论(0编辑  收藏  举报