A.Election 2(思维)
题意:
A
t
C
o
d
e
r
AtCoder
AtCoder 市正在举行市长选举。候选人是高桥和青木。
有
N
N
N 张有效选票投给两位候选人中的任何一位,目前正在进行计票。这里,
N
N
N 是奇数。
目前的计票结果是:高桥
T
T
T 票,青木
A
A
A 票。
请判断此时选举结果是否已经确定。
分析:
我们计算票数少的加上剩下的所有票能不能超过票数多的即可。
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b, c;
cin >> a >> b >> c;
if (min(b, c) + a - b - c > max(b, c))
cout << "No" << endl;
else
cout << "Yes" << endl;
return 0;
}
B. Vertical Writing(模拟)
题意:
给你一个横向书写的文本。将其转换为竖写,用 *
填充空格。
给你 N N N 个由小写英文字母组成的字符串 S 1 , S 2 , … , S N S_1, S_2, \dots, S_N S1,S2,…,SN 。设 M M M 为这些字符串的最大长度。
打印 M M M 个满足以下条件的字符串 T 1 , T 2 , … , T M T_1, T_2, \dots, T_M T1,T2,…,TM :
- 每个
T
i
T_i
Ti 由小写英文字母和
*
组成。 - 每个
T
i
T_i
Ti 不以
*
结尾。 - 每个
1
≤
i
≤
N
1 \leq i \leq N
1≤i≤N 都满足以下条件:
- 对于每个 1 ≤ j ≤ ∣ S i ∣ 1 \leq j \leq |S_i| 1≤j≤∣Si∣ , T j T_j Tj 的 ( N − i + 1 ) (N-i+1) (N−i+1) 个字符存在, T 1 , T 2 , … , T ∣ S i ∣ T_1, T_2, \dots, T_{|S_i|} T1,T2,…,T∣Si∣ 的 ( N − i + 1 ) (N-i+1) (N−i+1) 个字符按此顺序连接等于 S i S_i Si 。
- 对于每一个
∣
S
i
∣
+
1
≤
j
≤
M
|S_i| + 1 \leq j \leq M
∣Si∣+1≤j≤M ,
T
j
T_j
Tj 的
(
N
−
i
+
1
)
(N-i+1)
(N−i+1) 个字符要么不存在,要么是
*
。
这里, ∣ S i ∣ |S_i| ∣Si∣ 表示字符串 S i S_i Si 的长度。
分析:
我们将
n
n
n个字符串顺时针旋转
90
90
90度,然后对于每一行,从右往左,一旦碰到字符,后续再碰到 时,替换成*
即可。
代码:
#include <bits/stdc++.h>
using namespace std;
char tmp[105][105];
int main() {
int n, m = -1;
cin >> n;
for (int i = 0; i < n; i++) {
string s;
int l;
cin >> s;
l = s.length();
m = max(m, l);
for (int j = 0; j < l; j++)
tmp[i][j] = s[j];
}
for (int i = 0; i < m; i++) {
string s = "";
for (int j = n - 1; j >= 0; j--) {
if (tmp[j][i])
s += tmp[j][i];
else
s += '*';
}
while (s[s.length() - 1] == '*')
s = s.substr(0, s.length() - 1);
cout << s << endl;
}
return 0;
}
C.Balls and Bag Query(数据结构)
题意:
你有一个空袋子。给你 Q Q Q 个查询,必须按顺序处理。
有三种查询。
1 x
:将一个写有整数 x x x 的球放入袋子中。2 x
: 从袋子中取出一个写有整数 x x x 的球并丢弃。当给出这个查询时,可以保证袋子中有一个写着整数 x x x 的球。3
: 打印袋中写有不同整数的球的个数。
分析:
用 m a p map map维护一下各个数字球的个数,当 m a p [ x ] = 0 map[x]=0 map[x]=0时移除该元素,询问就是 m a p . s i z e ( ) map.size() map.size()。
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int q;
cin >> q;
map<int, int> tmp;
while (q--) {
int op;
cin >> op;
if (op == 1) {
int x;
cin >> x;
tmp[x]++;
} else if (op == 2) {
int x;
cin >> x;
tmp[x]--;
if (tmp[x] == 0)
tmp.erase(x);
} else {
cout << tmp.size() << endl;
}
}
return 0;
}
D.Cuboid Sum Query (思维)
题意:
给你一个正整数 N N N 和一个整数 A x , y , z A_{x,y,z} Ax,y,z ,每个整数 ( x , y , z ) (x, y, z) (x,y,z) 的三元组都是 1 ≤ x , y , z ≤ N 1 \leq x, y, z \leq N 1≤x,y,z≤N 。
你将得到以下格式的 Q Q Q 个查询,必须按顺序处理。
对于 i i i 查询 ( 1 ≤ i ≤ Q ) (1 \leq i \leq Q) (1≤i≤Q) ,我们会给你一个由整数 ( L x i , R x i , L y i , R y i , L z i , R z i ) (Lx_i, Rx_i, Ly_i, Ry_i, Lz_i, Rz_i) (Lxi,Rxi,Lyi,Ryi,Lzi,Rzi) 组成的元组 1 ≤ L x i ≤ R x i ≤ N 1 \leq Lx_i \leq Rx_i \leq N 1≤Lxi≤Rxi≤N 、 1 ≤ L y i ≤ R y i ≤ N 1 \leq Ly_i \leq Ry_i \leq N 1≤Lyi≤Ryi≤N 和 1 ≤ L z i ≤ R z i ≤ N 1 \leq Lz_i \leq Rz_i \leq N 1≤Lzi≤Rzi≤N 。查找:
∑ x = L x i R x i ∑ y = L y i R y i ∑ z = L z i R z i A x , y , z \displaystyle{\sum_{x=Lx_i}^{Rx_i} \sum_{y=Ly_i}^{Ry_i} \sum_{z=Lz_i}^{Rz_i} A_{x,y,z}} x=Lxi∑Rxiy=Lyi∑Ryiz=Lzi∑RziAx,y,z .
分析:
我们令 S i , j , k = ∑ x = 1 i − 1 ∑ y = 1 j − 1 ∑ z = 1 k − 1 A x , y , z S_{i,j,k}=\sum\limits_{x=1}^{i-1} \sum\limits_{y=1}^{j-1}\sum\limits_{z=1}^{k-1}A_{x,y,z} Si,j,k=x=1∑i−1y=1∑j−1z=1∑k−1Ax,y,z 为 1 ≤ i , j , k ≤ N + 1 1 \leq i,j,k \leq N+1 1≤i,j,k≤N+1 。(如果 i i i , j j j 或 k k k 为 0 0 0 ,我们定义为 S i , k , k = 0 S_{i,k,k}=0 Si,k,k=0 )。
那么 ∑ x = L x i R x i ∑ y = L y i R y i ∑ z = L z i R z i A x , y , z = S R x i + 1 , R y i + 1 , R z i + 1 − S L x i , R x i + 1 , R z i + 1 − S R x i + 1 , L y i , R z i + 1 − S R x i + 1 , R y i + 1 , L z i + S L x i , L y i , R z i + 1 + S L x i , R y i + 1 , L z i + S R x i + 1 , L y i , L z i − S L x i , L y i , L z i \sum\limits_{x=Lx_i}^{Rx_i} \sum\limits_{y=Ly_i}^{Ry_i} \sum\limits_{z=Lz_i}^{Rz_i} A_{x,y,z}=S_{Rx_i+1,Ry_i+1,Rz_i+1}-S_{Lx_i,Rx_i+1,Rz_i+1}-S_{Rx_i+1,Ly_i,Rz_i+1}-S_{Rx_i+1,Ry_i+1,Lz_i}+S_{Lx_i,Ly_i,Rz_i+1}+S_{Lx_i,Ry_i+1,Lz_i}+S_{Rx_i+1,Ly_i,Lz_i}-S_{Lx_i,Ly_i,Lz_i} x=Lxi∑Rxiy=Lyi∑Ryiz=Lzi∑RziAx,y,z=SRxi+1,Ryi+1,Rzi+1−SLxi,Rxi+1,Rzi+1−SRxi+1,Lyi,Rzi+1−SRxi+1,Ryi+1,Lzi+SLxi,Lyi,Rzi+1+SLxi,Ryi+1,Lzi+SRxi+1,Lyi,Lzi−SLxi,Lyi,Lzi 成立。
所以,如果我们能快速计算 S S S ,那么每个查询都能在恒定的时间内得到回答。
事实上,根据 S i , j , k = S i − 1 , j , k + S i , j − 1 , k + S i , j , k − 1 − S i − 1 , j − 1 , k − S i − 1 , j , k − 1 − S i , j − 1 , k − 1 + S i − 1 , j − 1 , k − 1 + A i − 1 , j − 1 , k − 1 S_{i,j,k}=S_{i-1,j,k}+S_{i,j-1,k}+S_{i,j,k-1}-S_{i-1,j-1,k}-S_{i-1,j,k-1}-S_{i,j-1,k-1}+S_{i-1,j-1,k-1}+A_{i-1,j-1,k-1} Si,j,k=Si−1,j,k+Si,j−1,k+Si,j,k−1−Si−1,j−1,k−Si−1,j,k−1−Si,j−1,k−1+Si−1,j−1,k−1+Ai−1,j−1,k−1 的性质, S S S 可以快速计算。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL a[105][105][105];
LL sum[105][105][105];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
for (int k = 0; k < n; ++k) {
cin >> a[i][j][k];
}
}
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
for (int k = 0; k < n; ++k) {
sum[i + 1][j + 1][k + 1] =
sum[i][j + 1][k + 1] + sum[i + 1][j][k + 1] +
sum[i + 1][j + 1][k] - sum[i][j][k + 1] - sum[i][j + 1][k] -
sum[i + 1][j][k] + sum[i][j][k] + a[i][j][k];
}
}
}
int q;
cin >> q;
for (int i = 0; i < q; ++i) {
int lx, rx, ly, ry, lz, rz;
cin >> lx >> rx >> ly >> ry >> lz >> rz;
lx--, ly--, lz--;
LL ans = sum[rx][ry][rz] - sum[lx][ry][rz] - sum[rx][ly][rz] -
sum[rx][ry][lz] + sum[lx][ly][rz] + sum[lx][ry][lz] +
sum[rx][ly][lz] - sum[lx][ly][lz];
cout << ans << endl;
}
return 0;
}
E.Manhattan Multifocal Ellipse (双指针)
题意:
给你一个二维平面上的 N N N 点 ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x N , y N ) (x_1, y_1), (x_2, y_2), \dots, (x_N, y_N) (x1,y1),(x2,y2),…,(xN,yN) 和一个非负整数 D D D 。
求 ∑ i = 1 N ( ∣ x − x i ∣ + ∣ y − y i ∣ ) ≤ D \displaystyle \sum_{i=1}^N (|x-x_i|+|y-y_i|) \leq D i=1∑N(∣x−xi∣+∣y−yi∣)≤D 的整数对 ( x , y ) (x, y) (x,y) 的个数。
分析:
观察 x i , y i x_i,y_i xi,yi的范围,可知 x , y x,y x,y的取值范围是 [ − 2 × 1 0 6 , 2 × 1 0 6 ] [-2 \times 10^6,2 \times 10^6] [−2×106,2×106] 。将 x , y x,y x,y分开来计算,枚举所有的 x x x,计算$ (|x-x \times i|) $的和(可以通过正反方向预处理前缀和来计算),对 y y y 同理。然后对于所有的 x , y x,y x,y,从两端开始双指针枚举和 ≤ D \le D ≤D的情况。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 3e5 + 10;
LL x[N], y[N], a[N], b[N], t[1000005], ans;
int main() {
int n, d;
cin >> n >> d;
for (int i = 1; i <= n; i++) {
cin >> x[i] >> y[i];
}
sort(x + 1, x + n + 1);
sort(y + 1, y + n + 1);
x[n + 1] = LONG_LONG_MAX;
y[n + 1] = LONG_LONG_MAX;
for (int i = 1; i <= n; i++) {
a[i] = a[i - 1] + x[i];
b[i] = b[i - 1] + y[i];
}
for (int i = -2e6; i <= 2e6; i++) {
LL tmp = upper_bound(x + 1, x + n + 2, i) - x;
LL id = i * (tmp - 1) - a[tmp - 1] + a[n] - a[tmp - 1] - i * (n - tmp + 1);
if (id <= d) {
t[id]++;
}
}
for (int i = 1; i <= d; i++) {
t[i] += t[i - 1];
}
for (int i = -2e6; i <= 2e6; i++) {
LL tmp = upper_bound(y + 1, y + n + 2, i) - y;
LL id = i * (tmp - 1) - b[tmp - 1] + b[n] - b[tmp - 1] - i * (n - tmp + 1);
if (id <= d) {
ans += t[d - id];
}
}
cout << ans << endl;
return 0;
}
F.Maximum Composition (dp)
题意:
给你 N N N 个线性函数 f 1 , f 2 , … , f N f_1, f_2, \ldots, f_N f1,f2,…,fN ,其中 f i ( x ) = A i x + B i f_i(x) = A_i x + B_i fi(x)=Aix+Bi .
求由 K K K 组成的序列 p = ( p 1 , p 2 , … , p K ) p = (p_1, p_2, \ldots, p_K) p=(p1,p2,…,pK) 中 f p 1 ( f p 2 ( … f p K ( 1 ) … ) ) f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots )) fp1(fp2(…fpK(1)…)) 的最大可能值。介于 1 1 1 与 N N N (含)之间的个不同整数的最大可能值 f p 1 ( f p 2 ( … f p K ( 1 ) … ) ) f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots )) fp1(fp2(…fpK(1)…)) 。
分析:
我们首先思考当用于序列
p
p
p 的
K
K
K 整数固定不变时,
p
p
p 具有什么样的性质?
可以发现:
f
i
(
f
j
(
x
)
)
f_i(f_j(x))
fi(fj(x)) 和
f
j
(
f
i
(
x
)
)
f_j(f_i(x))
fj(fi(x)) 的排序与
x
x
x 无关,完全取决于
A
i
−
1
B
i
\frac{A_i-1}{B_i}
BiAi−1 和
A
j
−
1
B
j
\frac{A_j-1}{B_j}
BjAj−1 的排序。如果是
A
i
−
1
B
i
\frac{A_i-1}{B_i}
BiAi−1
>
>
>
A
j
−
1
B
j
\frac{A_j-1}{B_j}
BjAj−1 ,那么就是
f
i
(
f
j
(
x
)
)
>
f
j
(
f
i
(
x
)
)
f_i(f_j(x))>f_j(f_i(x))
fi(fj(x))>fj(fi(x)) 。
根据这一性质,在给定 K K K 个整数用于 p p p 时,当 p p p 满足 A p 1 − 1 B p 1 ≥ A p 2 − 1 B p 2 ≥ … ≥ A p K − 1 B p K \frac{A_{p_1}-1}{B_{p_1}} \geq \frac{A_{p_2}-1}{B_{p_2}} \geq \ldots \geq \frac{A_{p_K}-1}{B_{p_K}} Bp1Ap1−1≥Bp2Ap2−1≥…≥BpKApK−1 时,值 f p 1 ( f p 2 ( … f p K ( 1 ) … ) ) f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots)) fp1(fp2(…fpK(1)…)) 取最大值。
为简单起见,假设对 ( A , B ) (A,B) (A,B) 进行排序,使 A 1 − 1 B 1 ≥ A 2 − 1 B 2 ≥ … A N − 1 B N \frac{A_1-1}{B_1} \geq \frac{A_2-1}{B_2} \geq \ldots \frac{A_N-1}{B_N} B1A1−1≥B2A2−1≥…BNAN−1 .
那么问题可以改写如下:
求介于
1
1
1 和
N
N
N 之间的整数序列
p
p
p 的最大值
f
p
1
(
f
p
2
(
…
f
p
K
(
1
)
…
)
)
f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots))
fp1(fp2(…fpK(1)…)) ,使得
p
1
<
p
2
<
…
<
p
N
p_1 < p_2 < \ldots < p_N
p1<p2<…<pN。
我们可以用
d
p
dp
dp来解决这问题。
当决定
p
K
,
p
K
−
1
,
…
p
K
−
i
p_K,p_{K-1},\ldots p_{K-i}
pK,pK−1,…pK−i 时,求
f
p
K
−
i
(
…
f
p
K
(
1
)
…
)
f_{p_{K-i}}(\ldots f_{p_K}(1)\ldots)
fpK−i(…fpK(1)…) 的最大值 $dp_{i,j}=( $从而求得
p
K
−
i
≥
j
)
p_{K-i} \geq j)
pK−i≥j) .
我们定义
d
p
i
,
j
=
max
(
d
p
i
,
j
+
1
,
A
j
×
d
p
i
−
1
,
j
+
1
+
B
j
)
dp_{i,j}=\text{max}(dp_{i,j+1},A_j \times dp_{i-1,j+1}+B_j)
dpi,j=max(dpi,j+1,Aj×dpi−1,j+1+Bj) ,所求答案为
d
p
K
,
1
dp_{K,1}
dpK,1 。
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> a(n), b(n);
for (int i = 0; i < n; ++i) {
cin >> a[i] >> b[i];
}
vector<int> num(n);
for (int i = 0; i < n; ++i)
num[i] = i;
sort(num.begin(), num.end(), [&](int i, int j) { return b[i] * (a[j] - 1) > b[j] * (a[i] - 1); });
vector<long long> dp(k + 1, -1e9);
dp[0] = 1;
for (auto i: num) {
vector<long long> tmp = dp;
for (int j = 0; j < k; ++j)
if (dp[j] != -1e9) {
tmp[j + 1] = max(tmp[j + 1], dp[j] * a[i] + b[i]);
}
dp = move(tmp);
}
cout << dp[k] << endl;
return 0;
}
赛后交流
在比赛结束后,会在交流群中给出比赛题解,同学们可以在赛后查看题解进行补题。
群号: 704572101,赛后大家可以一起交流做题思路,分享做题技巧,欢迎大家的加入。