Codeforces Round #548 (Div. 2)
A. Even Substrings
Description:
You are given a string s=s1s2…sn of length n, which only contains digits 1, 2, …, 9.
A substring s[l…r] of s is a string slsl+1sl+2…sr. A substring s[l…r] of s is called even if the number represented by it is even.
Find the number of even substrings of s. Note, that even if some substrings are equal as strings, but have different l and r, they are counted as different substrings.
Input:
The first line contains an integer n ( 1≤n≤65000) — the length of the string s.
The second line contains a string s of length n. The string s consists only of digits 1, 2, …, 9.
Output
Print the number of even substrings of 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 types of chocolates. There are ai chocolates of type 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 xi chocolates of type i (clearly, 0≤xi≤ai), then for all 1≤j<i at least one of the following must hold:
- xj=0 (you bought zero chocolates of type j)
- xj<xi (you bought less chocolates of type j than of type i)
For example, the array x=[0,0,1,2,10] satisfies the requirement above (assuming that all ai≥xi), while arrays x=[0,1,0], x=[5,5] and x=[3,2] don’t.
Calculate the maximum number of chocolates you can buy.
Input:
The first line contains an integer n ( 1≤n≤2⋅105), denoting the number of types of chocolate.
The next line contains n integers ai ( 1≤ai≤109), 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 vertices. Each of the n−1 edges of the tree is colored in either black or red.
You are also given an integer k. Consider sequences of k vertices. Let’s call a sequence [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 a1 and ending at ak. Start at a1, then go to a2 using the shortest path between a1 and a2, then go to a3 in a similar way, and so on, until you travel the shortest path between ak−1 and 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 then the following sequences are good: [1,4,7], [5,5,3] and [2,3,7]. The following sequences are not good: [1,4,6], [5,5,5], [3,7,3].
There are nk sequences of vertices, count how many of them are good. Since this number can be quite large, print it modulo 109+7.
Input:
The first line contains two integers n and k ( 2≤n≤105, 2≤k≤100), the size of the tree and the length of the vertex sequence.
Each of the next n−1 lines contains three integers ui, vi and xi ( 1≤ui,vi≤n, xi∈{0,1}), where ui and vi denote the endpoints of the corresponding edge and xi is the color of this edge ( 0 denotes red edge and 1 denotes black edge).
Output
Print the number of good sequences modulo 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 个节点且至少经过一次黑边的路径数
总路径方案数就是 kn ,考虑将树上黑边删除只保留红边,求出每个连通块的节点数 x,这样对每个连通块会有 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 students and m clubs in a college. The clubs are numbered from 1 to m. Each student has a potential pi and is a member of the club with index 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 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 days. Thus, every day the director chooses such team, that the team strength is maximized.
The mex of the multiset S is the smallest non-negative integer that is not present in S. For example, the mex of the {0,1,1,2,4,5,9} is 3, the mex of {1,2,3} is 0 and the mex of ∅ (empty set) is 0.
Input:
The first line contains two integers n and m ( 1≤m≤n≤5000), the number of students and the number of clubs in college.
The second line contains n integers p1,p2,…,pn ( 0≤pi<5000), where pi is the potential of the i-th student.
The third line contains n integers c1,c2,…,cn ( 1≤ci≤m), which means that i-th student is initially a member of the club with index ci.
The fourth line contains an integer d ( 1≤d≤n), number of days for which the director wants to know the maximum possible strength of the team.
Each of the next d lines contains an integer ki ( 1≤ki≤n), which means that ki-th student lefts their club on the i-th day. It is guaranteed, that the ki-th student has not left their club earlier.
Output
For each of the 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 ,每个人又归属于一个集合 c , 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;
}