文章目录
AtCoder Beginner Contest 417
A A Substring
You are given an N-character string S consisting of lowercase English letters.
Output the string of N−A−B characters obtained by removing the first A characters and the last B characters from S.
翻译:
给定一个由 N 个小写英文字母组成的字符串 S。
输出 S 字符串移除前 A个字符,后 B 个字符后的字符串。
分析:使用string中的 s.erase(pos, k) 删除 s中的从 pos 下标开始的连续 k个元素。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10, inf = 0x3f3f3f3f;
void solve() {
int n, a, b;
string s;
cin >> n >> a >> b >> s;
s.erase(0, a);
s.erase(s.size()-b, b);
cout << s;
}
int main() {
int T = 1; while (T--) solve();
return 0;
}
B Search and Delete
Takahashi has an integer sequence A = ( A 1 , A 2 , … , A N ) A=(A_1,A_2,…,A_N) A=(A1,A2,…,AN) of length N.
It is guaranteed that A is non-decreasing.
Takahashi performs M operations on this integer sequence.
In the i-th operation ( 1 ≤ i ≤ M ) (1\le i\le M) (1≤i≤M), he performs the following operation:
If the sequence A contains B i B_i Bi as an element, select one such element and delete it. If no such element exists, do nothing.
Note that since A is non-decreasing, the sequence after the operation is uniquely determined regardless of the choice of element, and remains non-decreasing.
Find A after performing M operations.
翻译:
高桥有一个长度为 N 的整数序列 A = ( A 1 , A 2 , … , A N ) A=(A_1,A_2,…,A_N) A=(A1,A2,…,AN)。
保证 A 是非递减的。
高桥对这个整数序列执行 M 次操作。在第 i ( 1 ≤ i ≤ M ) (1\le i\le M) (1≤i≤M) 次操作中,他执行以下操作:
如果序列 A 包含 B i B_i Bi 作为元素,选择其中一个这样的元素并删除它。如果不存在这样的元素,则不执行任何操作。
注意,由于 A 是非递减的,操作后的序列无论选择哪个元素都是唯一确定的,并且仍然保持非递减。
执行 M 次操作后找到 A 。
分析:数据范围很小,直接暴力模拟即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10, inf = 0x3f3f3f3f;
void solve() {
int n, m;
cin >> n >> m;
vector<int> a(n + 1), b(m + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= m; i++) cin >> b[i];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (b[i] == a[j]) {
a[j] = -1;
break;
}
}
}
for (int i = 1; i <= n; i++) {
if (a[i] != -1)
cout << a[i] << ' ';
}
}
int main() {
int T = 1; while (T--) solve();
return 0;
}
C Distance Indicators
You are given an integer sequence A = ( A 1 , A 2 , . . . A N ) A=(A_1,A_2,...A_N) A=(A1,A2,...AN) of length N.
Find how many pairs of integers (i,j) ( 1 ≤ i < j ≤ N 1\le i<j \le N 1≤i<j≤N) satisfy j − i = A i − A j j-i=A_i-A_j j−i=Ai−Aj.
Constraints: 1 ≤ N ≤ 2 × 1 0 5 , 1 ≤ A i ≤ 2 × 1 0 5 ( 1 ≤ i ≤ N ) 1\le N\le 2\times 10^5,1 \le A_i \le 2\times 10^5(1\le i\le N) 1≤N≤2×105,1≤Ai≤2×105(1≤i≤N)。
翻译:
你被给定一个长度为 N 的整数序列 A = ( A 1 , A 2 , . . . A N ) A=(A_1,A_2,...A_N) A=(A1,A2,...AN)。
找出有多少对整数 (i,j) ( 1 ≤ i < j ≤ N 1\le i<j \le N 1≤i<j≤N) 满足 j − i = A i − A j j-i=A_i-A_j j−i=Ai−Aj。
约束: 1 ≤ N ≤ 2 × 1 0 5 , 1 ≤ A i ≤ 2 × 1 0 5 ( 1 ≤ i ≤ N ) 1\le N\le 2\times 10^5,1\le A_i \le 2\times 10^5(1\le i\le N) 1≤N≤2×105,1≤Ai≤2×105(1≤i≤N)。
分析:数据范围较大,枚举复杂度为 O ( n 2 ) O(n^2) O(n2),考虑将原式变形:移项得 j − a j = i + a i ≥ 2 j-a_j =i+a_i \ge 2 j−aj=i+ai≥2,可以发现左右两边均是与当前位置有关的信息。
用 s t [ x ] + + st[x] ++ st[x]++ 表示 x x x 出现的次数加一。
由于答案的更新在 s t st st 更新前,所以保证了 i < j i<j i<j。
其实,无论答案更新在前还是在后,本题都不影响答案。证明如下:
- 由于后续本就需要计算,所以只需要考虑当前是否影响答案即可。
- 会影响答案的一定是 i + a i = i − a i i+a_i=i-a_i i+ai=i−ai,但是这是不可能的,所以不会影响答案。
答案需要开 long long。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5, inf = 0x3f3f3f3f;
void solve() {
ll n, ans = 0;
cin >> n;
vector<int> a(n + 1);
map<int, int> st;
for (int i = 1; i <= n; i++) {
cin >> a[i];
ans += st[i - a[i]];
st[i + a[i]]++;
}
cout << ans << "\n";
}
int main() {
int T = 1;
while (T--)
solve();
return 0;
}
D Takahashi’s Expectation
Takahashi will receive N N N presents.
He has a parameter called mood, which is a non-negative integer, and his mood changes every time he receives a present. Each present has three parameters: value P P P, mood increase A A A, and mood decrease B B B, and his mood changes as follows based on these parameters:
- When the value P P P of the received present is greater than or equal to his mood, he is happy with the present, and his mood increases by A A A.
- When the value P P P of the received present is less than his mood, he is disappointed with the present, and his mood decreases by B B B. However, if his mood is originally less than B B B, it becomes 0 0 0.
The i i i-th ( 1 ≤ i ≤ N ) (1\le i\le N) (1≤i≤N) present he receives has value P i P _ i Pi, mood increase A i A _ i Ai, and mood decrease B i B _ i Bi.
You are given Q Q Q questions, so answer all of them. In the i i i-th ( 1 ≤ i ≤ Q ) (1\le i\le Q) (1≤i≤Q) question, you are given a non-negative integer X i X _ i Xi, so answer the following question:
Find Takahashi’s mood after receiving all N N N presents when his mood is initially X i X _ i Xi.
翻译:
高桥将收到 N N N 份礼物。
他有一个名为心情的参数,是一个非负整数,每次收到礼物时,他的心情都会发生变化。每件礼物都有三个参数:价值 P P P 、心情上升 A A A 、心情下降 B B B ,根据这些参数,他的心情会发生如下变化:
- 当收到的礼物的值 P P P 大于或等于他的心情时,他对礼物感到高兴,心情增加 A A A 。
- 当收到的礼物的价值 P P P 小于他的心情时,他对礼物感到失望,心情会降低 B B B 。但是,如果他的心情原本小于 B B B ,则会变成 0 0 0 。
他收到的 i i i /- ( 1 ≤ i ≤ N ) (1\le i\le N) (1≤i≤N) 份礼物的价值为 P i P _ i Pi ,心情增加 A i A _ i Ai ,心情减少 B i B _ i Bi 。
你有 Q Q Q 个问题,请回答所有问题。在 i i i - ( 1 ≤ i ≤ Q ) (1\le i\le Q) (1≤i≤Q) 题中,你得到了一个非负整数 X i X _ i Xi ,请回答下面的问题:
求高桥收到所有 N N N 礼物后的心情,当他的心情最初为 X i X _ i Xi 时。
分析:
题目中数据如果采用暴力,复杂度为 O ( n q ) O(nq) O(nq),约 5 e 9 5e9 5e9——这里其实可以通过一些瞎搞的做法降低常数,大概降低 10 倍就可以通过了。自然,这在复杂度上是比较危险的。
正确的解法是这样的:可以看题目发现, P i , A i , B i ∈ [ 1 , 500 ] P_i,A_i,B_i \in [1,500] Pi,Ai,Bi∈[1,500], X i ∈ [ 0 , 1 0 9 ] X_i\in [0,10^9] Xi∈[0,109]。
可以想到 X i X_i Xi 的范围如此之大,实际上只需要和 500 500 500 进行比较,这是否可以考虑预处理一些较小的解,然后通过将 X X X 快速转为该区间的解,貌似可行。
预处理 d p i , j dp_{i,j} dpi,j 表示开始情绪值为 j j j,从第 i i i 个礼物开始收取完所有礼物后的情绪值。
初始化: d p n + 1 , j = j dp_{n+1, j}=j dpn+1,j=j
状态转移:
d p i , j = { d p i + 1 , j + a i if j ≤ p i d p i + 1 , j − a i if j > p i dp_{i,j} = \begin{cases} dp_{i+1, j+a_i} & \text{ if } j\le p_i \\ dp_{i+1, j-a_i} & \text{ if } j> p_i \end{cases} dpi,j={dpi+1,j+aidpi+1,j−ai if j≤pi if j>pi
目标: d p 1 , x dp_{1,x} dp1,x
- 当 x ≤ 1000 x\le 1000 x≤1000,可以直接得到答案 d p 1 , x dp_{1,x} dp1,x;
- 当 x > 1000 x>1000 x>1000,可以通过 x − ∑ i = 1 k B i x-\sum_{i=1}^k B_i x−∑i=1kBi,使得 x ≤ 1000 x\le 1000 x≤1000。
由于 B i > 0 B_i>0 Bi>0,所以构造的 B B B 前缀和 S i S_i Si 是单调递增的,可以二分得到答案。
x − S i ≤ 1000 → S i ≥ x − 1000 x-S_i\le 1000 \to S_i \ge x-1000 x−Si≤1000→Si≥x−1000。
如果不存在 i i i 满足该不等式,则证明 S n < x − 1000 S_n<x-1000 Sn<x−1000,答案为 x − S n x-S_n x−Sn;
如果存在 i i i 满足该不等式,则证明可以通过 x − S i x-S_i x−Si 使得 x ≤ 1000 x\le 1000 x≤1000,所以答案为 d p i + 1 , x − S i dp_{i+1, x-S_i} dpi+1,x−Si。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e4 + 5, inf = 0x3f3f3f3f;
int n, q, x, p[N], a[N], b[N], s[N], dp[N][1505];
signed main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> p[i] >> a[i] >> b[i];
s[i] = s[i - 1] + b[i];
}
for (int i = 0; i <= 1500; i++)
dp[n + 1][i] = i;
for (int i = n; i >= 0; i--)
for (int j = 0; j <= 1000; j++)
if (p[i] >= j)
dp[i][j] = dp[i + 1][j + a[i]];
else
dp[i][j] = dp[i + 1][max(0, j - b[i])];
cin >> q;
while (q--) {
cin >> x;
if (x <= 1000) {
cout << dp[1][x] << "\n";
continue;
}
int i = lower_bound(s + 1, s + 1 + n, x - 1000) - s;
if (i == n + 1)
cout << x - s[n] << "\n";
else
cout << dp[i + 1][x - s[i]] << "\n";
}
return 0;
}
E A Path in A Dictionary
You are given a simple connected undirected graph G with N vertices and M edges.
The vertices of G are numbered vertex 1, vertex 2, …, vertex N, and the i-th ( 1 ≤ i ≤ M ) (1\le i \le M) (1≤i≤M) edge connects vertices U i U_i Ui and V i V_i Vi.
Find the lexicographically smallest simple path from vertex X to vertex Y in G.
That is, find the lexicographically smallest among the integer sequences P = ( P 1 , P 2 , … , P ∣ P ∣ ) P=(P1 ,P2 ,…,P_{∣P∣}) P=(P1,P2,…,P∣P∣) that satisfy the following conditions:
- 1 ≤ P i ≤ N 1 \le P_i \le N 1≤Pi≤N
- If i ≠ j i\neq j i=j, then P i ≠ P j P_i\neq P_j Pi=Pj.
- P 1 = X P_1=X P1=X and P ∣ P ∣ = Y P_{∣P∣}=Y P∣P∣=Y.
- For 1 ≤ i ≤ ∣ P ∣ − 1 1\le i\le ∣P∣−1 1≤i≤∣P∣−1, there exists an edge connecting vertices P i P_i Pi and P i + 1 P_{i+1} Pi+1.
One can prove that such a path always exists under the constraints of this problem.
You are given T test cases, so find the answer for each.
翻译:
给定一个简单的连通无向图 G ,它有 N 个顶点和 M 条边。
G 的顶点编号为顶点 1、2 、… 、N ,第 i 条 ( 1 ≤ i ≤ M ) (1\le i \le M) (1≤i≤M) 边连接顶点 U i U_i Ui 和 V i V_i Vi。
在 G 中,找到从顶点 X 到顶点 Y 的字典序最小的简单路径。
也就是说,找到满足以下条件的整数序列 P = ( P 1 , P 2 , … , P ∣ P ∣ ) P=(P1 ,P2 ,…,P_{∣P∣}) P=(P1,P2,…,P∣P∣) 中字典序最小的序列:
- 1 ≤ P i ≤ N 1 \le P_i \le N 1≤Pi≤N
- 如果 i ≠ j i\neq j i=j, 那么 P i ≠ P j P_i\neq P_j Pi=Pj.
- P 1 = X P_1=X P1=X 且 P ∣ P ∣ = Y P_{∣P∣}=Y P∣P∣=Y.
- 对于 1 ≤ i ≤ ∣ P ∣ − 1 1\le i\le ∣P∣−1 1≤i≤∣P∣−1, 存在一条边连接顶点 P i P_i Pi 和 P i + 1 P_{i+1} Pi+1.
可以证明,在问题的约束条件下,这样的路径总是存在。
给出了 T 个测试用例,所以找出每个的答案。
分析:建图后按节点升序排序,dfs 遍历即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
const int N = 1e6 + 10, inf = 0x3f3f3f3f, inf2 = 1e18;
vector<int> G[N];
int a[N], n, m, x, y, p;
bool st[N], flag;
void dfs(int u) {
if (flag) return;
st[u] = 1, a[++p] = u;
if (u == y) {
for (int i = 1; i <= p; i++)
cout << a[i] << " \n"[i == p];
flag = 1; return;
}
for (auto& v : G[u]) {
if (st[v]) continue;
dfs(v);
}
--p;
}
void solve() {
cin >> n >> m >> x >> y;
p = 0, flag = 0;
memset(st, 0x00, sizeof st);
for (int i = 1; i <= n; i++) G[i].clear();
for (int i = 1, u, v; i <= m; i++) {
cin >> u >> v;
G[u].push_back(v), G[v].push_back(u);
}
for (int i = 1; i <= n; i++) sort(G[i].begin(), G[i].end());
dfs(x);
}
signed main() {
int T = 1;
cin >> T;
while (T--) solve();
return 0;
}
F Random Gathering
There are N N N plates arranged from left to right as plate 1 , 1, 1, plate 2 , … , 2,\ldots, 2,…, plate N N N. Initially, plate i ( 1 ≤ i ≤ N ) i\ (1\le i\le N) i (1≤i≤N) contains A i A _ i Ai stones.
You will perform M M M operations on these plates. In the i i i-th operation ( 1 ≤ i ≤ M ) (1\le i\le M) (1≤i≤M), two integers L i L _ i Li and R i R _ i Ri are given, and the following operations are performed in order:
- Remove all stones from the R i − L i + 1 R _ i-L _ i+1 Ri−Li+1 plates: plate L i , L _ i, Li, plate L i + 1 , … , L _ i+1,\ldots, Li+1,…, plate R i R _ i Ri.
- Uniformly randomly choose an integer between L i L _ i Li and R i R _ i Ri, inclusive, and let it be x x x.
- Place all the removed stones on plate x x x.
For i = 1 , 2 , … , N i=1,2,\ldots,N i=1,2,…,N, find the expected number, modulo 998244353 998244353 998244353, of stones placed on plate i i i when all M M M operations are completed.
Finding expected value modulo 998244353 998244353 998244353
It can be proved that the expected value you seek is always a rational number. Also, under the constraints of this problem, when that value is expressed as an irreducible fraction P Q \frac{P}{Q} QP, it can be proved that Q ≢ 0 ( m o d 998244353 ) Q \not\equiv 0 \pmod{998244353} Q≡0(mod998244353). Therefore, there is a unique integer R R R such that R × Q ≡ P ( m o d 998244353 ) , 0 ≤ R < 998244353 R \times Q \equiv P \pmod{998244353}, 0 \leq R \lt 998244353 R×Q≡P(mod998244353),0≤R<998244353. Finding the expected value modulo 998244353 998244353 998244353 means finding this R R R.
翻译:
有 N N N 个盘子,从左到右排列为盘子 1 , 1, 1, 盘子 2 , … , 2,\ldots, 2,…, 盘子 N N N 。最初,板块 i ( 1 ≤ i ≤ N ) i\ (1\le i\le N) i (1≤i≤N) 包含 A i A _ i Ai 块石头。
您将在这些板块上进行 M M M 次操作。在 i i i -th 运算 ( 1 ≤ i ≤ M ) (1\le i\le M) (1≤i≤M) 中,给出了两个整数 L i L _ i Li 和 R i R _ i Ri ,并依次进行了以下运算:
- 移除 R i − L i + 1 R _ i-L _ i+1 Ri−Li+1 盘中的所有棋子:盘子 L i , L _ i, Li, 盘子 L i + 1 , … , L _ i+1,\ldots, Li+1,…, 盘子 R i R _ i Ri 。
- 在 L i L _ i Li 和 R i R _ i Ri (含)之间统一随机选择一个整数,让它成为 x x x 。
- 将所有取出的棋子放入棋盘 x x x 中。
就 i = 1 , 2 , … , N i=1,2,\ldots,N i=1,2,…,N 而言,求当所有 M M M 运算完成后,放置在 i i i 盘中的石子的预期数目(模为 998244353 998244353 998244353 )。
求模数 998244353 998244353 998244353 的期望值。
可以证明,所求的期望值总是一个有理数。另外,在本题的限制条件下,当该值表示为不可约分数 P Q \frac{P}{Q} QP 时,可以证明 Q ≢ 0 ( m o d 998244353 ) Q \not\equiv 0 \pmod{998244353} Q≡0(mod998244353) 。因此,存在一个唯一的整数 R R R ,即 R × Q ≡ P ( m o d 998244353 ) , 0 ≤ R < 998244353 R \times Q \equiv P \pmod{998244353}, 0 \leq R \lt 998244353 R×Q≡P(mod998244353),0≤R<998244353 。求模为 998244353 998244353 998244353 的期望值就是求这个 R R R 。
分析:
根据期望值的线性关系,可知每个盘子操作后放的石子的期望数量 E = ∑ i = l r a i r − l + 1 E=\frac{\sum_{i=l}^r a_i}{r-l+1} E=r−l+1∑i=lrai
区间求和 [ l , r ] = ∑ i = l r a i [l,r]=\sum_{i=l}^r {a_i} [l,r]=∑i=lrai,区间修改 [ l , r ] [l,r] [l,r] 为 E E E,故而维护一个懒标记的线段树即可。
给定的模数为质数,使用费马小定理做逆元处理除法取模。
#include <bits/stdc++.h>
#define int long long
#define lowbit(x) (x & (-x))
typedef long long ll;
using namespace std;
const int N = 2e5 + 5, inf = 0x3f3f3f3f;
const int P = 998244353;
int n, m, a[N];
struct Node {
int l, r, sum, tag;
} tr[N << 2];
void pushup(Node& u, Node& l, Node& r) {
u.sum = l.sum + r.sum;
u.sum %= P;
u.tag = 0;
}
void pushup(int u) {
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void pushdown(Node& u, int tag) {
u.tag = tag;
u.sum = tag * (u.r - u.l + 1) % P;
u.sum %= P;
}
void pushdown(int u) {
if (tr[u].tag) {
pushdown(tr[u << 1], tr[u].tag);
pushdown(tr[u << 1 | 1], tr[u].tag);
tr[u].tag = 0;
}
}
void build(int u, int l, int r) {
if (l == r) {
tr[u] = {l, r, a[l], 0};
return;
}
int mid = l + r >> 1;
tr[u] = {l, r, 0, 0};
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
void modify(int u, int l, int r, int tag) {
if (l > tr[u].r || r < tr[u].l)
return;
if (tr[u].l >= l && tr[u].r <= r) {
pushdown(tr[u], tag);
return;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid)
modify(u << 1, l, r, tag);
if (r > mid)
modify(u << 1 | 1, l, r, tag);
pushup(u);
}
int query(int u, int l, int r) {
if (tr[u].l >= l && tr[u].r <= r)
return tr[u].sum;
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1, ans = 0;
if (l <= mid)
ans += query(u << 1, l, r), ans %= P;
if (r > mid)
ans += query(u << 1 | 1, l, r), ans %= P;
return ans;
}
int fpow(int a, int b) {
int res = 1;
while (b) {
if (b & 1)
res = res * a % P;
a = a * a % P, b >>= 1;
}
return res % P;
}
signed main() {
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
build(1, 1, n);
int l, r;
while (m--) {
cin >> l >> r;
int x = query(1, l, r) * fpow(r - l + 1, P - 2) % P;
modify(1, l, r, x);
}
for (int i = 1; i <= n; i++) {
int x = query(1, i, i);
cout << x << " \n"[i == n];
}
return 0;
}
G Binary Cat
Define strings S 0 S_0 S0 and S 1 S_1 S1 as S 0 = S_0= S0= 0
and S 1 = S_1= S1= 1
.
You are given Q Q Q queries, so process them in order.
In the i i i-th query ( 1 ≤ i ≤ Q ) (1\leq i\leq Q) (1≤i≤Q), you are given a triple of integers ( L i , R i , X i ) (L_i,R_i,X_i) (Li,Ri,Xi).
Let S i + 1 S_{i+1} Si+1 be the string obtained by concatenating S L i S_{L_i} SLi and S R i S_{R_i} SRi in this order. Then, find the X i X_i Xi-th character of S i + 1 S_{i+1} Si+1.
It is guaranteed that X i X_i Xi is at most the length of S i + 1 S_{i+1} Si+1.
翻译:
将字符串 S 0 S_0 S0 和 S 1 S_1 S1 定义为 S 0 = 0 S_0=0 S0=0 和 S 1 = 1 S_1=1 S1=1 。
我们会得到 Q Q Q 个查询,请按顺序处理它们。
在 i i i -查询 ( 1 ≤ i ≤ Q ) (1\leq i\leq Q) (1≤i≤Q) 中,你会得到一个整数三元组 ( L i , R i , X i ) (L_i,R_i,X_i) (Li,Ri,Xi) 。
假设 S i + 1 S_{i+1} Si+1 是按照这个顺序连接 S L i S_{L_i} SLi 和 S R i S_{R_i} SRi 得到的字符串。然后,找出 S i + 1 S_{i+1} Si+1 的 X i X_i Xi -th 字符。
可以保证 X i X_i Xi 最多是 S i + 1 S_{i+1} Si+1 的长度。