A.Wrong Answer(模拟)
题意:
给你两个整数 A A A和 B B B,它们介于 0 0 0和 9 9 9之间。
输出任何一个介于 0 0 0和 9 9 9之间且不等于 A + B A+B A+B的整数。
分析:
按题意判断并输出一个整数即可。
代码:
#include<bits/stdc++.h>using namespace std;int main() {int a, b;cin >> a >> b;for (int i = 0; i < 10; i++) {if (i != a + b) {cout << i << endl;break;}}return 0;
}
B.Adjacency Matrix(模拟)
题意:
有一个简单的无向图 G G G,其中有 N N N个顶点,顶点上标有数字 1 , 2 , … , N 1,2,\ldots,N 1,2,…,N。
给你 G G G的邻接矩阵 ( A i , j ) (A_{i,j}) (Ai,j)。也就是说,当且仅当 A i , j = 1 A_{i,j}=1 Ai,j=1时, G G G有一条边连接顶点 i i i和 j j j。
对于每个 i = 1 , 2 , … , N i=1,2,\ldots,N i=1,2,…,N,按升序输出与顶点 i i i直接相连的顶点的编号。
当且仅当顶点 i i i和 j j j之间有一条边相连时,顶点 i i i和 j j j才被认为是直接相连的。
分析:
如果是 1 1 1代表连通,输出其索引即可。
代码:
#include<bits/stdc++.h>using namespace std;int main() {int n;cin >> n;for (int t = 1; t <= n; t++) {for (int i = 1; i <= n; i++) {int x;cin >> x;if (x)cout << i << ' ';}cout << endl;}return 0;
}
C.343(遍历)
题意:
给你一个正整数 N N N。
求一个不大于 N N N的最大回文立方数。
正整数 K K K只有在满足以下两个条件时才被定义为回文立方数:
- 有一个正整数 x x x,使得 x 3 = K x^3=K x3=K.
- K K K的十进制表示不含前导零,而且是一个回文数。更确切地说,如果用介于 0 0 0和 9 9 9(含)之间的整数 A 0 , A 1 , … , A L − 2 A_0,A_1,\ldots,A_{L-2} A0,A1,…,AL−2和介于 1 1 1和 9 9 9(含)之间的整数 A L − 1 A_{L-1} AL−1将 K K K表示为 K = ∑ i = 0 L − 1 A i 1 0 i K=\sum\limits_{i = 0}^{L-1}A_i10^i K=i=0∑L−1Ai10i,则所有 i = 0 , 1 , … , L − 1 i=0,1,\ldots,L-1 i=0,1,…,L−1都是 A i = A L − 1 − i A_i=A_{L-1-i} Ai=AL−1−i。
分析:
n n n的范围是 1 e 18 1e18 1e18, 所以只需要遍历到 1 e 6 1e6 1e6即可,枚举然后判断是否为回文数即可。
代码:
#include<bits/stdc++.h>typedef long long LL;
using namespace std;bool check(LL n) {string s;while (n) {s += n % 10 + '0';n /= 10;}int len = s.size();s = '$' + s;for (int i = 1; i <= len / 2; i++)if (s[i] != s[len - i + 1])return false;return true;
}int main() {LL n;cin >> n;LL ans = 1;for (LL i = 2; i * i * i <= n; i++) {LL temp = i * i * i;if (check(temp)) {ans = temp;}}cout << ans << endl;return 0;
}
D.Diversity of Scores(遍历)
题意:
高桥正在举办一场有 N N N名选手参加的比赛,选手编号为 1 1 1至 N N N。选手们将争夺积分。目前,所有棋手的积分都是零。
高桥的预知能力让他知道选手们的分数将如何变化。具体来说,对于 i = 1 , 2 , … , T i=1,2,\dots,T i=1,2,…,T, A i A_i Ai选手的分数将在 i i i秒后增加 B i B_i Bi分。
高桥希望分数多样化,他想知道在每个时刻棋手的分数中会出现多少个不同的分数值。对于每个 i = 1 , 2 , … , T i=1,2,\dots,T i=1,2,…,T,求从现在起 i + 0.5 i+0.5 i+0.5秒钟后玩家分数中不同分值的数量。
例如,如果在某一时刻球员的得分分别为 10 10 10、 20 20 20、 30 30 30和 20 20 20,那么在该时刻球员的得分中有三个不同的分值。
分析:
初始化 0 0 0为 N N N,开始肯定是 1 1 1,因为都是 0 0 0,可以用 m a p < v a l u e s 值,人数 > m p map < values \text{值,人数} > mp map<values值,人数>mp来储存这个值,对于每一次相加 B , m p [ W [ A ] ] B, mp[W[A]] B,mp[W[A]]就要减去一个人数到了新的地方,以此类推即可。
代码:
#include<bits/stdc++.h>typedef long long LL;
using namespace std;
const LL N = 2e5 + 10;map<LL, LL> mp;
LL W[N];int main() {LL n, T;cin >> n >> T;mp[0] = n;LL ans = 1;for (LL i = 1; i <= T; i++) {LL A, B;cin >> A >> B;mp[W[A]]--;if (!mp[W[A]])ans--;W[A] += B;if (!mp[W[A]])ans++;mp[W[A]]++;cout << ans << endl;}return 0;
}
E.7x7x7(枚举)
题意:
在一个坐标空间中,我们想放置三个边长为 7 7 7的立方体,这样正好一个、两个、三个立方体所包含区域的体积分别为 V 1 V_1 V1、 V 2 V_2 V2、 V 3 V_3 V3。
对于三个整数 a a a、 b b b、 c c c,让 C ( a , b , c ) C(a,b,c) C(a,b,c)表示由 ( a ≤ x ≤ a + 7 ) ∧ ( b ≤ y ≤ b + 7 ) ∧ ( c ≤ z ≤ c + 7 ) (a\leq x\leq a+7)\land(b\leq y\leq b+7)\land(c\leq z\leq c+7) (a≤x≤a+7)∧(b≤y≤b+7)∧(c≤z≤c+7)代表的立方体区域。
判断是否有满足下列所有条件的九个整数 a 1 , b 1 , c 1 , a 2 , b 2 , c 2 , a 3 , b 3 , c 3 a_1,b_1,c_1,a_2,b_2,c_2,a_3,b_3,c_3 a1,b1,c1,a2,b2,c2,a3,b3,c3,如果存在,请找出一个这样的元组。
- ∣ a 1 ∣ , ∣ b 1 ∣ , ∣ c 1 ∣ , ∣ a 2 ∣ , ∣ b 2 ∣ , ∣ c 2 ∣ , ∣ a 3 ∣ , ∣ b 3 ∣ , ∣ c 3 ∣ ≤ 100 |a_1|,|b_1|,|c_1|,|a_2|,|b_2|,|c_2|,|a_3|,|b_3|,|c_3|\leq 100 ∣a1∣,∣b1∣,∣c1∣,∣a2∣,∣b2∣,∣c2∣,∣a3∣,∣b3∣,∣c3∣≤100
- 设 C i = C ( a i , b i , c i ) ( i = 1 , 2 , 3 ) C_i=C(a_i,b_i,c_i)\ (i=1,2,3) Ci=C(ai,bi,ci) (i=1,2,3)。
- 恰好包含 C 1 , C 2 , C 3 C_1,C_2,C_3 C1,C2,C3中一个的区域的体积为 V 1 V_1 V1。
- 恰好包含两个 C 1 , C 2 , C 3 C_1,C_2,C_3 C1,C2,C3的区域的体积是 V 2 V_2 V2。
- 所有 C 1 , C 2 , C 3 C_1,C_2,C_3 C1,C2,C3所包含的区域的体积是 V 3 V_3 V3。
分析:
假设第一个正方体的位置恒为 ( 0 , 0 , 0 ) (0,0,0) (0,0,0),暴力枚举第二、三个正方体的位置,判断每种放置方法是否合法即可
对于枚举位置,让三个正方体离太远没有意义,只需要枚举所有能使得三个正方体相交或至少有一个面重合的最大范围即可,则可以枚举的第二个正方体的三个维度的坐标值在 ( 0 , 7 ) (0,7) (0,7),第三个正方体的坐标值在 ( − 7 , 14 ) (-7,14) (−7,14)。
代码:
#include<bits/stdc++.h>using namespace std;int get_d(int x, int tx) {return max(0, min(x, tx) + 7 - max(x, tx));
}int get_d(int sx, int x, int tx) {return max(0, min({sx, x, tx}) + 7 - max({sx, x, tx}));
}int fun(int ax, int ay, int az, int bx, int by, int bz) {int dx = get_d(ax, bx), dy = get_d(ay, by), dz = get_d(az, bz);return dx * dy * dz;
}void solve() {int v1, v2, v3;cin >> v1 >> v2 >> v3;for (int x = 0; x <= 7; x++) {for (int y = 0; y <= 7; y++) {for (int z = 0; z <= 7; z++) {for (int tx = -7; tx <= 14; tx++) {for (int ty = -7; ty <= 14; ty++) {for (int tz = -7; tz <= 14; tz++) {int dx = get_d(0, x, tx);int dy = get_d(0, y, ty);int dz = get_d(0, z, tz);int tv3 = dx * dy * dz;if (tv3 != v3)continue;int tv2 = fun(0, 0, 0, x, y, z) + fun(0, 0, 0, tx, ty, tz) + fun(x, y, z, tx, ty, tz) -3 * tv3;if (tv2 != v2)continue;int tv1 = 3 * 7 * 7 * 7 - 3 * tv3 - 2 * tv2;if (tv1 != v1)continue;cout << "Yes" << endl;cout << "0 0 0 " << x << " " << y << " " << z << " " << tx << " " << ty << " " << tz<< endl;return;}}}}}}cout << "No" << endl;
}int main() {solve();return 0;
}
F.Second Largest Query(线段树)
题意:
给你一个长度为 N N N的序列 A = ( A 1 , A 2 , … , A N ) A=(A_1,A_2,\ldots,A_N) A=(A1,A2,…,AN)。
按照给出的顺序处理 Q Q Q个查询。每个查询属于以下两种类型之一:
- 类型 1 1 1:以
1 p x
的形式给出。将 A p A_p Ap的值改为 x x x。 - 类型 2 2 2:输出 ( A l , A l + 1 , … , A r ) (A_l,A_{l+1},\ldots,A_r) (Al,Al+1,…,Ar)中第二大数值的出现次数。更准确地说,输出满足 l ≤ i ≤ r l\leq i\leq r l≤i≤r的整数 i i i的个数,即在 A l , A l + 1 , … , A r A_l,A_{l+1},\ldots,A_r Al,Al+1,…,Ar中正好有一个大于 A i A_i Ai的不同值。
分析:
可以直接用线段树维护四个信息,每个节点维护这个区间对应的最大值、次大值、以及他们各自的出现次数,使用线段树板子加上求第二大的数即可。
代码:
#include<bits/stdc++.h>using namespace std;template<class Info, class Merge = std::plus<Info>>struct SegmentTree {const int n;const Merge merge;vector<Info> info;SegmentTree(int n) : n(n), merge(Merge()), info(4 << std::__lg(n)) {}SegmentTree(vector<Info> init) : SegmentTree(init.size()) {function<void(int, int, int)> build = [&](int p, int l, int r) {if (r - l == 1) {info[p] = init[l];return;}int m = (l + r) / 2;build(2 * p, l, m);build(2 * p + 1, m, r);pull(p);};build(1, 0, n);}void pull(int p) {info[p] = merge(info[2 * p], info[2 * p + 1]);}void modify(int p, int l, int r, int x, const Info &v) {if (r - l == 1) {info[p] = v;return;}int m = (l + r) / 2;if (x < m) {modify(2 * p, l, m, x, v);} else {modify(2 * p + 1, m, r, x, v);}pull(p);}void modify(int p, const Info &v) {modify(1, 0, n, p, v);}Info rangeQuery(int p, int l, int r, int x, int y) {if (l >= y || r <= x) {return Info();}if (l >= x && r <= y) {return info[p];}int m = (l + r) / 2;return merge(rangeQuery(2 * p, l, m, x, y), rangeQuery(2 * p + 1, m, r, x, y));}Info rangeQuery(int l, int r) {return rangeQuery(1, 0, n, l, r);}
};struct Info {int mx1 = -1;int cnt1 = 0;int mx2 = -2;int cnt2 = 0;
};Info operator+(Info a, Info b) {if (a.mx1 == b.mx1) {if (a.mx2 < b.mx2) {swap(a, b);}a.cnt1 += b.cnt1;if (a.mx2 == b.mx2) {a.cnt2 += b.cnt2;}return a;}if (a.mx1 < b.mx1) {swap(a, b);}if (b.mx1 > a.mx2) {a.mx2 = b.mx1;a.cnt2 = b.cnt1;} else if (b.mx1 == a.mx2) {a.cnt2 += b.cnt1;}return a;
}int main() {int N, Q;cin >> N >> Q;vector<int> A(N);for (int i = 0; i < N; i++) {cin >> A[i];}SegmentTree<Info> seg(N);for (int i = 0; i < N; i++) {seg.modify(i, Info{A[i], 1, -1, 0});}while (Q--) {int type;cin >> type;if (type == 1) {int p, x;cin >> p >> x;p--;seg.modify(p, {x, 1, -1, 0});} else {int l, r;cin >> l >> r;l--;cout << seg.rangeQuery(l, r).cnt2 << endl;}}return 0;
}
赛后交流
在比赛结束后,会在交流群中给出比赛题解,同学们可以在赛后查看题解进行补题。
群号: 704572101,赛后大家可以一起交流做题思路,分享做题技巧,欢迎大家的加入。