Codeforces Round #396 (Div. 2)

Posted Storm_Spirit

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #396 (Div. 2)相关的知识,希望对你有一定的参考价值。

  AB都是大水题。

  C题,题意稍微有点晦涩。但是还是一个比较简单的dp(虽然我不是独立的做出来的= =)。感觉我dp掌握的不是很好啊;看到这题突然想起前几天碰到的一题:不考虑顺序的整数划分问题。C题代码如下:

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <iostream>
 5 #include <string>
 6 using namespace std;
 7 const int N = 1000 + 5;
 8 typedef long long ll;
 9 const int mod = 1e9 + 7;
10 
11 int n;
12 char s[N];
13 int a[30];
14 int dp[N];
15 int minn[N];
16 
17 int main()
18 {
19     cin >> n;
20     scanf("%s",s+1);
21     for(int i=1;i<=26;i++) scanf("%d",a+i);
22     dp[0] = 1;
23     int maxx = 0;
24     for(int i=1;i<=n;i++) minn[i] = 1111;
25     for(int i=1;i<=n;i++)
26     {
27         int temp = 1111;
28         for(int j=i;j>=1;j--)
29         {
30             int now = s[j] - \'a\' + 1;
31             temp = min(temp, a[now]);
32             if(temp >= i-j+1)
33             {
34                 dp[i] = (dp[i] + dp[j-1]) % mod;
35                 minn[i] = min(minn[i], minn[j-1] + 1);
36                 maxx = max(maxx, i-j+1);
37             }
38             else break;
39         }
40     }
41     cout << dp[n] << endl;
42     cout << maxx << endl;
43     cout << minn[n] << endl;
44     return 0;
45 }
C

 

  D题,是个带权并查集。我记得去年寒假的时候写过这种题目,然后就一直没接触过了= =。近几天稍微复习一下这个专题好了。代码如下:

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <iostream>
 5 #include <string>
 6 #include <map>
 7 #include <vector>
 8 #include <set>
 9 using namespace std;
10 const int N = 100000 + 5;
11 typedef long long ll;
12 const int mod = 1e9 + 7;
13 typedef pair<int,int> pii;
14 
15 int n,m,q;
16 int root[N],rnk[N];
17 map<string,int> M;
18 void init()
19 {
20     for(int i=1;i<=n;i++) root[i] = i, rnk[i] = 0;
21 }
22 int find(int x)
23 {
24     if(x == root[x]) return x;
25     int y = root[x];
26     root[x] = find(root[x]);
27     rnk[x] = (rnk[x] + rnk[y]) % 2;
28     return root[x];
29 }
30 bool connect(int x,int y,int op)
31 {
32     int rx = find(x);
33     int ry = find(y);
34     if(rx != ry)
35     {
36         root[ry] = rx;
37         rnk[ry] = (op + rnk[x] - rnk[y] + 2) % 2;
38     }
39     else
40     {
41         int temp = (rnk[x] - rnk[y] + 2) % 2;
42         if(temp != op) return false;
43     }
44     return true;
45 }
46 
47 int main()
48 {
49     cin >> n >> m >> q;
50     for(int i=1;i<=n;i++)
51     {
52         string s;
53         cin >> s;
54         M[s] = i;
55     }
56     init();
57     while(m--)
58     {
59         int op;
60         string x,y;
61         cin >> op >> x >> y;
62         puts(connect(M[x],M[y],op-1) ? "YES" : "NO");
63     }
64     while(q--)
65     {
66         string x,y;
67         cin >> x >> y;
68         int rx = find(M[x]);
69         int ry = find(M[y]);
70         if(rx != ry) puts("3");
71         else printf("%d\\n",(rnk[M[x]]-rnk[M[y]]+2) % 2 + 1);
72     }
73     return 0;
74 }
D

 

  E题还是比较有意思的。具体做法是在dfs的时候二进制下把各个位置的已经出现过的1和0记录下来,然后直接做贡献即可。具体见代码:

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <iostream>
 5 #include <string>
 6 #include <map>
 7 #include <vector>
 8 #include <set>
 9 using namespace std;
10 const int N = 100000 + 5;
11 typedef long long ll;
12 const int mod = 1e9 + 7;
13 typedef pair<int,int> pii;
14 
15 int n;
16 vector<int> G[N];
17 int a[N];
18 int cnt[N][30][2];
19 ll dfs(int u,int fa)
20 {
21     ll ans = 0;
22     for(int i=0;i<22;i++)
23     {
24         cnt[u][i][(a[u] & (1<<i)) != 0]++;
25         ans += (1LL<<i) * cnt[u][i][1];
26     }
27     for(int now=0;now<G[u].size();now++)
28     {
29         int v = G[u][now];
30         if(v == fa) continue;
31         ans += dfs(v,u);
32         for(int i=0;i<22;i++)
33         {
34             for(int j=0;j<2;j++)
35             {
36                 ans += (1LL<<i) * cnt[u][i][j] * cnt[v][i][j^1];
37             }
38             for(int j=0;j<2;j++)
39             {
40                 cnt[u][i][j] += cnt[v][i][j ^ ((a[u] & (1<<i))) != 0];
41             }
42         }
43     }
44     return ans;
45 }
46 
47 int main()
48 {
49     cin >> n;
50     for(int i=1;i<=n;i++) scanf("%d",a+i);
51     for(int i=1;i<n;i++)
52     {
53         int x,y;
54         scanf("%d%d",&x,&y);
55         G[x].push_back(y);
56         G[y].push_back(x);
57     }
58     cout << dfs(1,-1) << endl;
59     return 0;
60 }
E

 

以上是关于Codeforces Round #396 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #396 (Div. 2) C. Mahmoud and a Message DP

Codeforces Round #396 (Div. 2) C题Mahmoud and a Message(dp)解题报告

Codeforces Round #396 (Div. 2) D题Mahmoud and a Dictionary(并查集)解题报告

Codeforces Round #396 (Div. 2)C. Mahmoud and a Message(dp)

Codeforces Round #396(Div. 2) A. Mahmoud and Longest Uncommon Subsequence

Codeforces Round #396 (Div. 2)D. Mahmoud and a Dictionary(带权并查集)