A- Wrong Answer
思路:
- 跳过
第一种写法
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 2e3 + 5;
using ll = long long;
void solve()
{
int a, b;
cin >> a >> b;
for(int i = 0; i < 10; i ++)
{
if(i != a + b)
{
cout << i << endl;
return ;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int t = 1;
//cin >> t;
while(t --)
solve();
return 0;
}
第二种写法——jiangly
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a, b;
cin >> a >> b;
cout << !(a + b) << endl;
return 0;
}
B- Adjacency Matrix
思路:
- 数据量不大,枚举模拟即可
第一种写法
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 1e2 + 10;
using ll = long long;
int a[N][N];
void solve()
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
cin >> a[i][j];
for(int i = 1; i <= n; i ++)
{
vector<int> v;
for(int j = 1; j <= n; j ++)
{
if(a[j][i])
v.push_back(j);
}
for(int j = 0; j < v.size(); j ++)
cout << v[j] << " \n"[j == v.size() - 1];
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int t = 1;
//cin >> t;
while(t --)
solve();
return 0;
}
第二种写法——jiangly
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= n; j ++)
{
int a;
cin >> a;
if(a)
cout << j << ' ';
}
cout << '\n';
}
return 0;
}
C - 343
思路:
- 1 ≤ i ≤ 1 e 6 1\leq i \leq1e6 1≤i≤1e6,数据量不大,可以轻松枚举。
- 只需每次判断是否为回文数即可
第一种写法
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 1e2 + 10;
using ll = long long;
//判断是否为回文数
bool check(ll n)
{
string s;
//拆解,并存入s中
while(n)
{
s += n % 10 + '0';
n /= 10;
}
int len = (int)s.size();
s = '$' + s;
//回文数具有对称性,判断
for(int i = 1; i <= len / 2; i ++)
if(s[i] != s[len - i + 1])
return false;
return true;
}
void solve()
{
ll n, i;
cin >> n;
for(i = 1e6; i * i * i > n; i --);
for(; i * i * i >= 1; i --)
{
ll temp = i * i * i;
if(check(temp))
{
cout << temp << endl;
return ;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int t = 1;
//cin >> t;
while(t --)
solve();
return 0;
}
第二种写法——jiangly
#include <bits/stdc++.h>
using i64 = long long;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
i64 n;
std::cin >> n;
i64 ans = 0;
for(i64 a = 1; a * a * a <= n; a ++)
{
i64 x = a * a * a;
//转换成string类型
std::string s = std::to_string(x);
//只要转置之后与原字符串相等,就是回文数
//相当于reverse,但不会对字符串本身进行修改。
if(s == std::string(s.rbegin(), s.rend()))
ans = a * a * a;
}
std::cout << ans << '\n';
return 0;
}
D - Diversity of Scores
思路:
- 用两个map模拟:
- 一个储存为 m p 1 [ 选手编号,该选手分数 ] mp1[选手编号, 该选手分数] mp1[选手编号,该选手分数]
- 一个储存为 m p 2 [ 分数,为此分数的人数 ] mp2[分数,为此分数的人数] mp2[分数,为此分数的人数]
第一种写法
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 2e5 + 10;
using ll = long long;
map<int, ll> mp;
map<ll, int> mp1;
int a[N], b[N];
void solve()
{
int n, t;
cin >> n >> t;
//输入
for(int i = 1; i <= t; i ++)
cin >> a[i] >> b[i];
mp1[0] = n;
for(int i = 1; i <= t; i ++)
{
//分数进行了变化,原来的分数的人输-1
mp1[mp[a[i]]] --;
//如果原来的分数的人数变为1,则删除mp1此分数结点
if(mp1[mp[a[i]]] == 0)
mp1.erase(mp[a[i]]);//删除
//加分
mp[a[i]] += b[i];
//加分后的分数的人数+1
mp1[mp[a[i]]] ++;
//输出第二种mp的尺寸即可
cout << mp1.size() << endl;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int t = 1;
//cin >> t;
while(t --)
solve();
return 0;
}
第二种写法——jiangly
#include <bits/stdc++.h>
using i64 = long long;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, t;
std::cin >> n >> t;
//存储这个分数有多少人
std::map<i64, int> cnt;
//存储这个序号的选手有多少分数
std::vector<i64> score(n);
//初始都为每个人的分数都为0
cnt[0] = n;
while(t --)
{
int a, b;
//输入
std::cin >> a >> b;
//使序号统一
a --;
//若原分数人数减一后为零,直接删除该结点
if(-- cnt[score[a]] == 0)
cnt.erase(score[a]);
//加分
score[a] += b;
//此分数人数+1
cnt[score[a]] ++;
//输出尺寸
std::cout << cnt.size() << '\n';
}
return 0;
}
E - 7x7x7
参考来源——abc官方题解
思路:
-
把其中一个正方体固定在: ( 0 , 0 , 0 ) (0, 0, 0) (0,0,0)位置是可行的。因为所求的答案只与三个立方体的相对位置相关。而题目所限制的 a , b , c a,b,c a,b,c的范围足够大。因此可行。
-
那么难点主要就是求 V 1 , V 2 , V 3 V1,V2,V3 V1,V2,V3的大小。由题目可得:
- v 3 = V ( C 1 ∩ C 2 ∩ C 3 ) v_3=V(C_1\cap C_2\cap C_3) v3=V(C1∩C2∩C3)
- v 2 = V ( C 1 ∩ C 2 ) + V ( C 1 ∩ C 3 ) + V ( C 2 ∩ C 3 ) − 3 v 3 v_2=V(C_1\cap C_2)+V(C_1\cap C_3)+V(C_2\cap C_3)-3v_3 v2=V(C1∩C2)+V(C1∩C3)+V(C2∩C3)−3v3
- v 1 = 3 × 7 3 − 2 v 2 − 3 v 3 v_1=3\times 7^3-2v_2-3v_3 v1=3×73−2v2−3v3
-
最主要是求得 V 2 , V 3 V2,V3 V2,V3的体积的值,那如何去求:
-
推导: ( 两个立方体的公共部分的长,宽,高 ) (两个立方体的公共部分的长,宽,高) (两个立方体的公共部分的长,宽,高)
-
max { a i , a j } ≤ x ≤ min { a i + 7 , a j + 7 } \max\{a_i,a_j\}\leq x\leq \min\{a_i+7,a_j+7\} max{ai,aj}≤x≤min{ai+7,aj+7}
-
max { b i , b j } ≤ y ≤ min { b i + 7 , b j + 7 } \max\{b_i,b_j\}\leq y\leq \min\{b_i+7,b_j+7\} max{bi,bj}≤y≤min{bi+7,bj+7}
-
max { c i , c j } ≤ z ≤ min { c i + 7 , c j + 7 } \max\{c_i,c_j\}\leq z\leq \min\{c_i+7,c_j+7\} max{ci,cj}≤z≤min{ci+7,cj+7}
因此可以得到 max { 0 , min { a i , a j } + 7 − max { a i , a j } } × max { 0 , min { b i , b j } + 7 − max { b i , b j } } × max { 0 , min { c i , c j } + 7 − max { c i , c j } } \max\{0, \min\{a_i,a_j\}+7-\max\{a_i,a_j\}\} \times \max\{0, \min\{b_i,b_j\}+7-\max\{b_i,b_j\}\} \times \max\{0,\min\{c_i,c_j\}+7-\max\{c_i,c_j\}\} max{0,min{ai,aj}+7−max{ai,aj}}×max{0,min{bi,bj}+7−max{bi,bj}}×max{0,min{ci,cj}+7−max{ci,cj}}。
- 如果是三个立方体,依旧同理可得。
以下是代码部分:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
//计算正方体两两公共的体积
int f(int a1, int b1, int c1, int a2, int b2, int c2) {
int res = 1;
res *= max(0, min(a1, a2) + 7 - max(a1, a2));
res *= max(0, min(b1, b2) + 7 - max(b1, b2));
res *= max(0, min(c1, c2) + 7 - max(c1, c2));
return res;
}
// 计算正方体三三公共的体积
int f(int a1, int b1, int c1, int a2, int b2, int c2, int a3, int b3, int c3) {
int res = 1;
res *= max(0, min({a1, a2, a3}) + 7 - max({a1, a2, a3}));
res *= max(0, min({b1, b2, b3}) + 7 - max({b1, b2, b3}));
res *= max(0, min({c1, c2, c3}) + 7 - max({c1, c2, c3}));
return res;
}
int main() {
int v1, v2, v3;
cin >> v1 >> v2 >> v3;
//以固定C1,枚举C2,C3的位置。想要由公共体积,枚举范围为这些。
for (int a2 = -7; a2 <= 7; a2++) {
for (int b2 = -7; b2 <= 7; b2++) {
for (int c2 = -7; c2 <= 7; c2++) {
for (int a3 = -7; a3 <= 7; a3++) {
for (int b3 = -7; b3 <= 7; b3++) {
for (int c3 = -7; c3 <= 7; c3++)
{
//正方体三三公共的体积的值
int nv3 = f(0, 0, 0, a2, b2, c2, a3, b3, c3);
//正方体两两公共的体积的值的和
int nv2 = f(0, 0, 0, a2, b2, c2) + f(0, 0, 0, a3, b3, c3) + f(a2, b2, c2, a3, b3, c3) -
nv3 * 3;
//正方体私有的体积的值的和
int nv1 = 3 * 7 * 7 * 7 - nv2 * 2 - nv3 * 3;
if (v1 != nv1 || v2 != nv2 || v3 != nv3) continue;
printf("Yes\n0 0 0 %d %d %d %d %d %d\n", a2, b2, c2, a3, b3, c3);
return 0;
}
}
}
}
}
}
cout << "No" << endl;
}
F - Second Largest Query
这题可去B站观看视频讲解bilibili的一个up :tarjan98
思路:
- 线段树储存该区段的最大值 m x 1 mx1 mx1, 最大值个数 c n t 1 cnt1 cnt1, 次大值 m x 2 mx2 mx2, 次大值个数 c n t 2 cnt2 cnt2
以下是代码部分——代码参考来源wsy0655
#include <bits/stdc++.h>
using namespace std;
#define ls p<<1
#define rs (p<<1)|1
using ll = long long;
const int N = 2e5 + 10;
int n, q, a[N];
//结点数量最大不超过4 * N
struct segment_tree{
// l为左边界, r为右边界, cnt1为最大值的数量, cnt2为次大值的数量
// mx1为最大值, mx2 为次大值
int l, r, cnt1, cnt2, mx1, mx2;
}t[N << 2];
void push_up(int p)
{
//最大值为左下分叉点和右下分叉结点中的最大值
t[p].mx1 = max(t[ls].mx1, t[rs].mx1);
//分情况归类mx1 和 mx2
//最大值的数目更新
if(t[ls].mx1 > t[rs].mx1) t[p].cnt1 = t[ls].cnt1;
else if(t[ls].mx1 < t[rs].mx1) t[p].cnt1 = t[rs].cnt1;
else t[p].cnt1 = t[ls].cnt1 + t[rs].cnt1;
//map储存记录mx1, mx2的数目
map<int, int> cnt;
cnt[t[ls].mx1] += t[ls].cnt1;
cnt[t[rs].mx1] += t[rs].cnt1;
cnt[t[ls].mx2] += t[ls].cnt2;
cnt[t[rs].mx2] += t[rs].cnt2;
//map内部已经从小到大排序
auto it = cnt.lower_bound(t[p].mx1);
// 求出次大值的位置
it --;
//次大值赋值
t[p].mx2 = it -> first;
if(it->first == 0) t[p].cnt2 = 0;
else t[p].cnt2 = cnt[it -> first];
}
//通过递归建立线段树
void build(int p, int l, int r)
{
//该区段的左边界和右边界
t[p].l = l, t[p].r = r;
//当只有一个元素时, 结束递归
if(l == r)
{
t[p].mx1 = a[l], t[p].mx2 = t[p].cnt2 = 0, t[p].cnt1 = 1;
return ;
}
//计算中间值
int mid = l + ((r - l) >> 1);
//递归建立线段树,先建立左边的,再建立右边的。
build(ls, l, mid), build(rs, mid + 1, r);
push_up(p);
}
void modify(int p, int x, int k)
{
if (x == t[p].l && t[p].r == x)
{
t[p].mx1 = k, t[p].mx2 = 0, t[p].cnt1 = 1, t[p].cnt2 = 0;
return ;
}
int mid = (t[p].l + t[p].r) >> 1;
if (x <= mid) modify(ls, x, k);
if (x > mid) modify(rs, x, k);
push_up(p);
}
//和push_up()函数一个代码,为查询
segment_tree query(int p, int l, int r)
{
//如果包含这个子段范围,直接返回
if (l <= t[p].l && t[p].r <= r) return t[p];
//中间区间边界
int mid = (t[p].l + t[p].r) >> 1;
//在右子段
if (r <= mid) return query(ls, l, r);
//在左子段
if (l > mid) return query(rs, l, r);
//x为左子段返回内容, y为右子段返回内容
segment_tree x = query(ls, l, r), y = query(rs, l, r), res;
//比较左右子段哪个更好
//分类讨论赋最大值的值
res.mx1 = max(x.mx1, y.mx1);
if (x.mx1 > y.mx1) res.cnt1 = x.cnt1;
else if (x.mx1 < y.mx1) res.cnt1 = y.cnt1;
else res.cnt1 = x.cnt1 + y.cnt1;
//次大值赋值
map<int, int> cnt;
cnt[x.mx1] += x.cnt1;
cnt[y.mx1] += y.cnt1;
cnt[x.mx2] += x.cnt2;
cnt[y.mx2] += y.cnt2;
auto it = cnt.lower_bound(res.mx1);
it--;
res.mx2 = it->first;
if (it->first == 0) res.cnt2 = 0;
else res.cnt2 = cnt[it->first];
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> q;
for (int i = 1; i <= n; i++) cin >> a[i];
build(1, 1, n);
while (q--)
{
int op, l, r;
cin >> op >> l >> r;
if (op == 1) modify(1, l, r);
if (op == 2) cout << query(1, l, r).cnt2 << "\n";
}
return 0;
}