Codeforces Round #548 (Div. 2)

A. Even Substrings

Description:

You are given a string s = s 1 s 2 s n s=s_1s_2\dots s_n s=s1s2sn of length n n n, which only contains digits 1 1 1, 2 2 2, …, 9 9 9.
A substring s [ l r ] s[l \dots r] s[lr] of s s s is a string s l s l + 1 s l + 2 s r s_l s_{l + 1} s_{l + 2} \ldots s_r slsl+1sl+2sr. A substring s [ l r ] s[l \dots r] s[lr] of s s s is called even if the number represented by it is even.
Find the number of even substrings of s s s. Note, that even if some substrings are equal as strings, but have different l l l and r r r, they are counted as different substrings.

Input:

The first line contains an integer n n n ( 1 n 65000 1 \le n \le 65000 1n65000) — the length of the string s s s.
The second line contains a string s s s of length n n n. The string s s s consists only of digits 1 1 1, 2 2 2, …, 9 9 9.

Output

Print the number of even substrings of s s s.

Sample Input:

4
1234

Sample Output:

6

Sample Input:

4
2244

Sample Output:

10

题目链接

求偶数子串数量

对每位是偶数地数求和即可

AC代码:

#include <bits/stdc++.h>

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0); std::cout.tie(0);

  long long n; std::cin >> n;
  std::string str; std::cin >> str;

  long long ans = 0;
  for (long long i = 0; i < n; ++i) {
    if ((str[i] - '0') % 2 == 0) ans += i + 1;
  }
  
  std::cout << ans << '\n';
  return 0;
}

B. Chocolates

Description:

You went to the store, selling n n n types of chocolates. There are a i a_i ai chocolates of type i i i in stock.
You have unlimited amount of cash (so you are not restricted by any prices) and want to buy as many chocolates as possible. However if you buy x i x_i xi chocolates of type i i i (clearly, 0 x i a i 0 \le x_i \le a_i 0xiai), then for all 1 j &lt; i 1 \le j &lt; i 1j<i at least one of the following must hold:

  • x j = 0 x_j = 0 xj=0 (you bought zero chocolates of type j j j)
  • x j &lt; x i x_j &lt; x_i xj<xi (you bought less chocolates of type j j j than of type i i i)

For example, the array x = [ 0 , 0 , 1 , 2 , 10 ] x = [0, 0, 1, 2, 10] x=[0,0,1,2,10] satisfies the requirement above (assuming that all a i x i a_i \ge x_i aixi), while arrays x = [ 0 , 1 , 0 ] x = [0, 1, 0] x=[0,1,0], x = [ 5 , 5 ] x = [5, 5] x=[5,5] and x = [ 3 , 2 ] x = [3, 2] x=[3,2] don’t.
Calculate the maximum number of chocolates you can buy.

Input:

The first line contains an integer n n n ( 1 n 2 1 0 5 1 \le n \le 2 \cdot 10^5 1n2105), denoting the number of types of chocolate.
The next line contains n n n integers a i a_i ai ( 1 a i 1 0 9 1 \le a_i \le 10^9 1ai109), denoting the number of chocolates of each type.

Output

Print the maximum number of chocolates you can buy.

Sample Input:

5
1 2 1 3 6

Sample Output:

10

Sample Input:

5
3 2 5 4 10

Sample Output:

20

Sample Input:

4
1 1 1 1

Sample Output:

1

题目链接

求每个元素不超过上限的严格上升序列最大和

倒推每位都去可能的最大值即可

AC代码:

#include <bits/stdc++.h>

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0); std::cout.tie(0);

  long long n; std::cin >> n;
  std::vector<long long> a(n);
  for (auto &it : a) std::cin >> it;

  std::vector<long long> b(n);
  b[n - 1] = a[n - 1];
  long long ans = b[n - 1];
  for (int i = n - 2; i >= 0; --i) {
    b[i] = std::max((long long)0, std::min(a[i], b[i + 1] - 1ll));
    ans += b[i];
  }

  std::cout << ans << '\n';
  return 0;
}

C. Edgy Trees

Description:

You are given a tree (a connected undirected graph without cycles) of n n n vertices. Each of the n 1 n - 1 n1 edges of the tree is colored in either black or red.
You are also given an integer k k k. Consider sequences of k k k vertices. Let’s call a sequence [ a 1 , a 2 , , a k ] [a_1, a_2, \ldots, a_k] [a1,a2,,ak] good if it satisfies the following criterion:

We will walk a path (possibly visiting same edge/vertex multiple times) on the tree, starting from a 1 a_1 a1 and ending at a k a_k ak. Start at a 1 a_1 a1, then go to a 2 a_2 a2 using the shortest path between a 1 a_1 a1 and a 2 a_2 a2, then go to a 3 a_3 a3 in a similar way, and so on, until you travel the shortest path between a k 1 a_{k-1} ak1 and a k a_k ak. If you walked over at least one black edge during this process, then the sequence is good. Consider the tree on the picture. If k = 3 k=3 k=3 then the following sequences are good: [ 1 , 4 , 7 ] [1, 4, 7] [1,4,7], [ 5 , 5 , 3 ] [5, 5, 3] [5,5,3] and [ 2 , 3 , 7 ] [2, 3, 7] [2,3,7]. The following sequences are not good: [ 1 , 4 , 6 ] [1, 4, 6] [1,4,6], [ 5 , 5 , 5 ] [5, 5, 5] [5,5,5], [ 3 , 7 , 3 ] [3, 7, 3] [3,7,3].
There are n k n^k nk sequences of vertices, count how many of them are good. Since this number can be quite large, print it modulo 1 0 9 + 7 10^9+7 109+7.

Input:

The first line contains two integers n n n and k k k ( 2 n 1 0 5 2 \le n \le 10^5 2n105, 2 k 100 2 \le k \le 100 2k100), the size of the tree and the length of the vertex sequence.
Each of the next n 1 n - 1 n1 lines contains three integers u i u_i ui, v i v_i vi and x i x_i xi ( 1 u i , v i n 1 \le u_i, v_i \le n 1ui,vin, x i { 0 , 1 } x_i \in \{0, 1\} xi{0,1}), where u i u_i ui and v i v_i vi denote the endpoints of the corresponding edge and x i x_i xi is the color of this edge ( 0 0 0 denotes red edge and 1 1 1 denotes black edge).

Output

Print the number of good sequences modulo 1 0 9 + 7 10^9 + 7 109+7.

Sample Input:

4 4
1 2 1
2 3 1
3 4 1

Sample Output:

252

Sample Input:

4 6
1 2 0
1 3 0
1 4 0

Sample Output:

0

Sample Input:

3 5
1 2 1
2 3 0

Sample Output:

210

题目链接

一棵树上的边有红色的黑色之分,求包含 k k k 个节点且至少经过一次黑边的路径数

总路径方案数就是 k n k^{n} kn ,考虑将树上黑边删除只保留红边,求出每个连通块的节点数 x,这样对每个连通块会有 x k x^{k} xk 种方案不合法,在总数中减去即可

AC代码:

#include <bits/stdc++.h>
const long long mod = 1e9 + 7;

long long QuickPow(long long k, long long n) {
  if (n == 0) return 1;
  long long ans = 1;
  while (n) {
    if (n & 1) ans = ans * k % mod;
    k = k * k % mod;
    n >>= 1;
  }
  return ans;
}

long long n, k;
std::vector<std::vector<int>> g;
std::vector<bool> vis;

int Dfs(int cur) {
  vis[cur] = true;
  int cnt = 1;
  for (auto &it : g[cur]) {
    if (vis[it]) continue;
    cnt += Dfs(it);
  }
  return cnt;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0); std::cout.tie(0);

  std::cin >> n >> k;
  g.resize(n); vis.assign(n, false);
  for (int i = 1, u, v, x; i < n; ++i) {
    std::cin >> u >> v >> x;
    --u; --v;
    if (x == 0) {
      g[u].emplace_back(v);
      g[v].emplace_back(u);
    }
  }

  long long ans = QuickPow(n, k);
  for (int i = 0; i < n; ++i) {
    if (!vis[i])
      ans = (ans - QuickPow(Dfs(i), k) + mod) % mod;
  }

  std::cout << ans << '\n';
  return 0;
}

E. Maximize Mex

Description:

There are n n n students and m m m clubs in a college. The clubs are numbered from 1 1 1 to m m m. Each student has a potential p i p_i pi and is a member of the club with index c i c_i ci. Initially, each student is a member of exactly one club. A technical fest starts in the college, and it will run for the next d d d days. There is a coding competition every day in the technical fest.
Every day, in the morning, exactly one student of the college leaves their club. Once a student leaves their club, they will never join any club again. Every day, in the afternoon, the director of the college will select one student from each club (in case some club has no members, nobody is selected from that club) to form a team for this day’s coding competition. The strength of a team is the mex of potentials of the students in the team. The director wants to know the maximum possible strength of the team for each of the coming d d d days. Thus, every day the director chooses such team, that the team strength is maximized.
The mex of the multiset S S S is the smallest non-negative integer that is not present in S S S. For example, the mex of the { 0 , 1 , 1 , 2 , 4 , 5 , 9 } \{0, 1, 1, 2, 4, 5, 9\} {0,1,1,2,4,5,9} is 3 3 3, the mex of { 1 , 2 , 3 } \{1, 2, 3\} {1,2,3} is 0 0 0 and the mex of \varnothing (empty set) is 0 0 0.

Input:

The first line contains two integers n n n and m m m ( 1 m n 5000 1 \leq m \leq n \leq 5000 1mn5000), the number of students and the number of clubs in college.
The second line contains n n n integers p 1 , p 2 , , p n p_1, p_2, \ldots, p_n p1,p2,,pn ( 0 p i &lt; 5000 0 \leq p_i &lt; 5000 0pi<5000), where p i p_i pi is the potential of the i i i-th student.
The third line contains n n n integers c 1 , c 2 , , c n c_1, c_2, \ldots, c_n c1,c2,,cn ( 1 c i m 1 \leq c_i \leq m 1cim), which means that i i i-th student is initially a member of the club with index c i c_i ci.
The fourth line contains an integer d d d ( 1 d n 1 \leq d \leq n 1dn), number of days for which the director wants to know the maximum possible strength of the team.
Each of the next d d d lines contains an integer k i k_i ki ( 1 k i n 1 \leq k_i \leq n 1kin), which means that k i k_i ki-th student lefts their club on the i i i-th day. It is guaranteed, that the k i k_i ki-th student has not left their club earlier.

Output

For each of the d d d days, print the maximum possible strength of the team on that day.

Sample Input:

5 3
0 1 2 2 0
1 2 2 3 2
5
3
2
4
5
1

Sample Output:

3
1
1
1
0

Sample Input:

5 3
0 1 2 2 1
1 3 2 3 2
5
4
2
3
5
1

Sample Output:

3
2
2
1
0

Sample Input:

5 5
0 1 2 4 5
1 2 3 4 5
4
2
3
5
4

Sample Output:

1
1
1
1

题目链接

每个人有一个权值 p p p ,每个人又归属于一个集合 c c c k k k 次操作每次删除一个人,之后求出每个集合选一个人组成集合的最小非负数的最大值

考虑把操作离线并反转,将集合与每个人的权值建图,每次添加人(加边)跑最大流(二分图匹配)即可

AC代码:

#include <bits/stdc++.h>

namespace NetFlow {
  const int inf = 0x3f3f3f3f;
  int s, t;
  struct edge {int to, cap, rev;};
  std::vector<std::vector<edge>> g;
  std::vector<bool> vis;

  void Init(int n) {
    s = 0; t = n;
    g.resize(n + 1);
  }

  void AddEdge(int u, int v, int cap, int rev = 0) {
    g[u].push_back((edge){v, cap, (int)g[v].size()});
    g[v].push_back((edge){u, rev, (int)g[u].size() - 1});
  }

  int Dfs(int u, int t, int flow) {
    if (u == t) return flow;
    vis[u] = true;
    for (edge &e : g[u]) {
      if (!vis[e.to] && e.cap > 0) {
        int f = Dfs(e.to, t, std::min(e.cap, flow));
        if (f > 0) {
          e.cap -= f;
          g[e.to][e.rev].cap += f;
          return f;
        }
      }
    }
    return 0;
  }

  int GetMaxFlow(int s, int t) {
    int ans = 0;
    while (true) {
      vis.assign(t + 1, false);
      int flow = Dfs(s, t, inf);
      if (flow == 0) return ans;
      ans += flow;
    }
  }
};

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0); std::cout.tie(0);

  int n, m; std::cin >> n >> m;
  std::vector<int> p(n, 0), c(n, 0);
  std::vector<std::vector<int>> cnt(5005);
  for (int i = 0; i < n; ++i) std::cin >> p[i];
  for (int i = 0; i < n; ++i) {
    std::cin >> c[i];
    --c[i];
  }
  int d; std::cin >> d;
  std::vector<int> q(d);
  std::vector<bool> del(n, false);
  for (int i = 0; i < d; ++i) {
    std::cin >> q[i];
    --q[i];
    del[q[i]] = true;
  }

  int s = m + 5005, t = s + 1;
  NetFlow::Init(t);
  for (int i = 0; i < m; ++i) NetFlow::AddEdge(s, i, 1);
  for (int i = 0; i < n; ++i)
    if (!del[i]) NetFlow::AddEdge(c[i], m + p[i], 1);

  std::vector<int> ans(d);
  int cur_mx = -1, cur_match = 0;
  for (int i = d - 1; i >= 0; --i) {
    while (cur_mx < 5001 && cur_match == cur_mx + 1) {
      ++cur_mx;
      NetFlow::AddEdge(m + cur_mx, t, 1);
      cur_match += NetFlow::GetMaxFlow(s, t);
    }
    ans[i] = cur_mx;
    NetFlow::AddEdge(c[q[i]], m + p[q[i]], 1);
    cur_match += NetFlow::GetMaxFlow(s, t);
  }

  for (int i = 0; i < d; ++i) std::cout << ans[i] << '\n';
  return 0;
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务