A. Even Substrings

Description:

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

Input:

The first line contains an integer nn (1n650001 \le n \le 65000) — the length of the string ss.
The second line contains a string ss of length nn. The string ss consists only of digits 11, 22, …, 99.

Output

Print the number of even substrings of ss.

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 nn types of chocolates. There are aia_i chocolates of type ii 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 xix_i chocolates of type ii (clearly, 0xiai0 \le x_i \le a_i), then for all 1j&lt;i1 \le j &lt; i at least one of the following must hold:

  • xj=0x_j = 0 (you bought zero chocolates of type jj)
  • xj&lt;xix_j &lt; x_i (you bought less chocolates of type jj than of type ii)

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

Input:

The first line contains an integer nn (1n21051 \le n \le 2 \cdot 10^5), denoting the number of types of chocolate.
The next line contains nn integers aia_i (1ai1091 \le a_i \le 10^9), 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 nn vertices. Each of the n1n - 1 edges of the tree is colored in either black or red.
You are also given an integer kk. Consider sequences of kk vertices. Let’s call a sequence [a1,a2,,ak][a_1, a_2, \ldots, a_k] good if it satisfies the following criterion:

Codeforces Round #548 (Div. 2)

We will walk a path (possibly visiting same edge/vertex multiple times) on the tree, starting from a1a_1 and ending at aka_k. Start at a1a_1, then go to a2a_2 using the shortest path between a1a_1 and a2a_2, then go to a3a_3 in a similar way, and so on, until you travel the shortest path between ak1a_{k-1} and aka_k. 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=3k=3 then the following sequences are good: [1,4,7][1, 4, 7], [5,5,3][5, 5, 3] and [2,3,7][2, 3, 7]. The following sequences are not good: [1,4,6][1, 4, 6], [5,5,5][5, 5, 5], [3,7,3][3, 7, 3].
There are nkn^k sequences of vertices, count how many of them are good. Since this number can be quite large, print it modulo 109+710^9+7.

Input:

The first line contains two integers nn and kk (2n1052 \le n \le 10^5, 2k1002 \le k \le 100), the size of the tree and the length of the vertex sequence.
Each of the next n1n - 1 lines contains three integers uiu_i, viv_i and xix_i (1ui,vin1 \le u_i, v_i \le n, xi{0,1}x_i \in \{0, 1\}), where uiu_i and viv_i denote the endpoints of the corresponding edge and xix_i is the color of this edge (00 denotes red edge and 11 denotes black edge).

Output

Print the number of good sequences modulo 109+710^9 + 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

题目链接

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

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

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 nn students and mm clubs in a college. The clubs are numbered from 11 to mm. Each student has a potential pip_i and is a member of the club with index cic_i. Initially, each student is a member of exactly one club. A technical fest starts in the college, and it will run for the next dd 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 dd days. Thus, every day the director chooses such team, that the team strength is maximized.
The mex of the multiset SS is the smallest non-negative integer that is not present in SS. For example, the mex of the {0,1,1,2,4,5,9}\{0, 1, 1, 2, 4, 5, 9\} is 33, the mex of {1,2,3}\{1, 2, 3\} is 00 and the mex of \varnothing (empty set) is 00.

Input:

The first line contains two integers nn and mm (1mn50001 \leq m \leq n \leq 5000), the number of students and the number of clubs in college.
The second line contains nn integers p1,p2,,pnp_1, p_2, \ldots, p_n (0pi&lt;50000 \leq p_i &lt; 5000), where pip_i is the potential of the ii-th student.
The third line contains nn integers c1,c2,,cnc_1, c_2, \ldots, c_n (1cim1 \leq c_i \leq m), which means that ii-th student is initially a member of the club with index cic_i.
The fourth line contains an integer dd (1dn1 \leq d \leq n), number of days for which the director wants to know the maximum possible strength of the team.
Each of the next dd lines contains an integer kik_i (1kin1 \leq k_i \leq n), which means that kik_i-th student lefts their club on the ii-th day. It is guaranteed, that the kik_i-th student has not left their club earlier.

Output

For each of the dd 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

题目链接

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

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

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;
}

相关文章: