A.Election 2(思维)
题意:
AtCoderAtCoderAtCoder 市正在举行市长选举。候选人是高桥和青木。
有 NNN 张有效选票投给两位候选人中的任何一位,目前正在进行计票。这里, NNN 是奇数。
目前的计票结果是:高桥 TTT 票,青木 AAA 票。
请判断此时选举结果是否已经确定。
分析:
我们计算票数少的加上剩下的所有票能不能超过票数多的即可。
代码:
#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(模拟)
题意:
给你一个横向书写的文本。将其转换为竖写,用 * 填充空格。
给你 NNN 个由小写英文字母组成的字符串 S1,S2,…,SNS_1, S_2, \dots, S_NS1,S2,…,SN 。设 MMM 为这些字符串的最大长度。
打印 MMM 个满足以下条件的字符串 T1,T2,…,TMT_1, T_2, \dots, T_MT1,T2,…,TM :
- 每个 TiT_iTi 由小写英文字母和
*组成。 - 每个 TiT_iTi 不以
*结尾。 - 每个 1≤i≤N1 \leq i \leq N1≤i≤N 都满足以下条件:
- 对于每个 1≤j≤∣Si∣1 \leq j \leq |S_i|1≤j≤∣Si∣ , TjT_jTj 的 (N−i+1)(N-i+1)(N−i+1) 个字符存在, T1,T2,…,T∣Si∣T_1, T_2, \dots, T_{|S_i|}T1,T2,…,T∣Si∣ 的 (N−i+1)(N-i+1)(N−i+1) 个字符按此顺序连接等于 SiS_iSi 。
- 对于每一个 ∣Si∣+1≤j≤M|S_i| + 1 \leq j \leq M∣Si∣+1≤j≤M , TjT_jTj 的 (N−i+1)(N-i+1)(N−i+1) 个字符要么不存在,要么是
*。
这里, ∣Si∣|S_i|∣Si∣ 表示字符串 SiS_iSi 的长度。
分析:
我们将nnn个字符串顺时针旋转909090度,然后对于每一行,从右往左,一旦碰到字符,后续再碰到 时,替换成*即可。
代码:
#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(数据结构)
题意:
你有一个空袋子。给你 QQQ 个查询,必须按顺序处理。
有三种查询。
1 x:将一个写有整数 xxx 的球放入袋子中。2 x: 从袋子中取出一个写有整数 xxx 的球并丢弃。当给出这个查询时,可以保证袋子中有一个写着整数 xxx 的球。3: 打印袋中写有不同整数的球的个数。
分析:
用mapmapmap维护一下各个数字球的个数,当map[x]=0map[x]=0map[x]=0时移除该元素,询问就是map.size()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 (思维)
题意:
给你一个正整数 NNN 和一个整数 Ax,y,zA_{x,y,z}Ax,y,z ,每个整数 (x,y,z)(x, y, z)(x,y,z) 的三元组都是 1≤x,y,z≤N1 \leq x, y, z \leq N1≤x,y,z≤N 。
你将得到以下格式的 QQQ 个查询,必须按顺序处理。
对于 iii 查询 (1≤i≤Q)(1 \leq i \leq Q)(1≤i≤Q) ,我们会给你一个由整数 (Lxi,Rxi,Lyi,Ryi,Lzi,Rzi)(Lx_i, Rx_i, Ly_i, Ry_i, Lz_i, Rz_i)(Lxi,Rxi,Lyi,Ryi,Lzi,Rzi) 组成的元组 1≤Lxi≤Rxi≤N1 \leq Lx_i \leq Rx_i \leq N1≤Lxi≤Rxi≤N 、 1≤Lyi≤Ryi≤N1 \leq Ly_i \leq Ry_i \leq N1≤Lyi≤Ryi≤N 和 1≤Lzi≤Rzi≤N1 \leq Lz_i \leq Rz_i \leq N1≤Lzi≤Rzi≤N 。查找:
∑x=LxiRxi∑y=LyiRyi∑z=LziRziAx,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 .
分析:
我们令Si,j,k=∑x=1i−1∑y=1j−1∑z=1k−1Ax,y,zS_{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+11 \leq i,j,k \leq N+11≤i,j,k≤N+1 。(如果 iii , jjj 或 kkk 为 000 ,我们定义为 Si,k,k=0S_{i,k,k}=0Si,k,k=0 )。
那么 ∑x=LxiRxi∑y=LyiRyi∑z=LziRziAx,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\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 成立。
所以,如果我们能快速计算 SSS ,那么每个查询都能在恒定的时间内得到回答。
事实上,根据 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−1S_{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 的性质, SSS 可以快速计算。
代码:
#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 (双指针)
题意:
给你一个二维平面上的 NNN 点 (x1,y1),(x2,y2),…,(xN,yN)(x_1, y_1), (x_2, y_2), \dots, (x_N, y_N)(x1,y1),(x2,y2),…,(xN,yN) 和一个非负整数 DDD 。
求 ∑i=1N(∣x−xi∣+∣y−yi∣)≤D\displaystyle \sum_{i=1}^N (|x-x_i|+|y-y_i|) \leq Di=1∑N(∣x−xi∣+∣y−yi∣)≤D 的整数对 (x,y)(x, y)(x,y) 的个数。
分析:
观察xi,yix_i,y_ixi,yi的范围,可知x,yx,yx,y的取值范围是[−2×106,2×106][-2 \times 10^6,2 \times 10^6][−2×106,2×106] 。将x,yx,yx,y分开来计算,枚举所有的xxx,计算$ (|x-x \times i|) $的和(可以通过正反方向预处理前缀和来计算),对 yyy 同理。然后对于所有的 x,yx,yx,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)
题意:
给你 NNN 个线性函数 f1,f2,…,fNf_1, f_2, \ldots, f_Nf1,f2,…,fN ,其中 fi(x)=Aix+Bif_i(x) = A_i x + B_ifi(x)=Aix+Bi .
求由 KKK 组成的序列 p=(p1,p2,…,pK)p = (p_1, p_2, \ldots, p_K)p=(p1,p2,…,pK) 中 fp1(fp2(…fpK(1)…))f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots ))fp1(fp2(…fpK(1)…)) 的最大可能值。介于 111 与 NNN (含)之间的个不同整数的最大可能值 fp1(fp2(…fpK(1)…))f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots ))fp1(fp2(…fpK(1)…)) 。
分析:
我们首先思考当用于序列 ppp 的 KKK 整数固定不变时, ppp 具有什么样的性质?
可以发现:
fi(fj(x))f_i(f_j(x))fi(fj(x)) 和 fj(fi(x))f_j(f_i(x))fj(fi(x)) 的排序与 xxx 无关,完全取决于 Ai−1Bi\frac{A_i-1}{B_i}BiAi−1 和 Aj−1Bj\frac{A_j-1}{B_j}BjAj−1 的排序。如果是 Ai−1Bi\frac{A_i-1}{B_i}BiAi−1>>> Aj−1Bj\frac{A_j-1}{B_j}BjAj−1 ,那么就是 fi(fj(x))>fj(fi(x))f_i(f_j(x))>f_j(f_i(x))fi(fj(x))>fj(fi(x)) 。
根据这一性质,在给定 KKK 个整数用于 ppp 时,当 ppp 满足 Ap1−1Bp1≥Ap2−1Bp2≥…≥ApK−1BpK\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 时,值 fp1(fp2(…fpK(1)…))f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots))fp1(fp2(…fpK(1)…)) 取最大值。
为简单起见,假设对 (A,B)(A,B)(A,B) 进行排序,使 A1−1B1≥A2−1B2≥…AN−1BN\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 .
那么问题可以改写如下:
求介于 111 和 NNN 之间的整数序列 ppp 的最大值 fp1(fp2(…fpK(1)…))f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots))fp1(fp2(…fpK(1)…)) ,使得 p1<p2<…<pNp_1 < p_2 < \ldots < p_Np1<p2<…<pN。
我们可以用dpdpdp来解决这问题。
当决定 pK,pK−1,…pK−ip_K,p_{K-1},\ldots p_{K-i}pK,pK−1,…pK−i 时,求 fpK−i(…fpK(1)…)f_{p_{K-i}}(\ldots f_{p_K}(1)\ldots)fpK−i(…fpK(1)…) 的最大值 $dp_{i,j}=( $从而求得 pK−i≥j)p_{K-i} \geq j)pK−i≥j) .
我们定义dpi,j=max(dpi,j+1,Aj×dpi−1,j+1+Bj)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) ,所求答案为 dpK,1dp_{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,赛后大家可以一起交流做题思路,分享做题技巧,欢迎大家的加入。

626

被折叠的 条评论
为什么被折叠?



