AtCoder Beginner Contest 343
B - Adjacency Matrix
难度: ⭐
题目大意
给定一个无向图的邻接矩阵, 问每个节点都和哪些节点相练;
解题思路
没啥好说的;
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 2e18;
typedef pair<int, int> PII;
int n, m;
int p[200][200];
signed main(){
cin >> n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
cin >> p[i][j];
if(p[i][j] == 1) cout << j << ' ';
}
cout << endl;
}
return 0;
}
C - 343
难度: ⭐⭐
题目大意
给定一个数n, 输出不大于n的回文立方数x
解题思路
n的范围是1e18, 所以可以遍历1e6然后判断立方回文即可;
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 2e18;
typedef pair<int, int> PII;
int n, m, res;
bool check(int u){
int p[20];
int idx = 0;
while(u){
p[++idx] = u % 10;
u /= 10;
}
for(int i = 1, j = idx; i <= j; i++, j--){
if(p[i] != p[j]) return false;
}
return true;
}
signed main(){
cin >> n;
for(int i = 1; i * i * i <= n; i++){
int k = i * i * i;
if(check(k)) res = k;
}
cout << res;
return 0;
}
D - Diversity of Scores
难度: ⭐⭐⭐
题目大意
现在有n个人, 每人初始分数为0; 现在有m次分配, 每次都会给Ai人分配Bi分; 请问每次分配后这n个人一共有多少种分数, 0也算一种;
解题思路
用数组标记一下当前所有分数的个数即可;
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 2e18;
typedef pair<int, int> PII;
int n, m, res = 1;
int p[N];
map<int, int> mp;
signed main(){
cin >> n >> m;
mp[0] = n;
for(int i = 1; i <= m; i++){
int a, b;
cin >> a >> b;
p[a] += b;
if(!mp[p[a]]) res++;
mp[p[a]]++;
mp[p[a] - b]--;
if(!mp[p[a] - b]) res--;
cout << res << endl;
}
return 0;
}
E - 7x7x7
难度: ⭐⭐⭐⭐
F - Second Largest Query
难度: ⭐⭐⭐⭐
题目大意
给定一个长度为n的数组, 现在进行m次操作, 操作分为两种, 一是把下标为a的数改成b, 而是输出区间[l, r]之间第二大数的个数;
解题思路
第一次在赛时切F题, 必须记录一下; 很明显的线段树; 节点我们可以维护区间的左右端点, 最大值以及最大值的个数, 次大值以及次大值的个数;
build函数和modify函数和普通线段树一样, query函数我们可以返回结构体类型, 方便更新和输出;
本题关键还是在于pushup函数; 更新一个区间时, 其左区间有最大值和次大值, 右区间也有最大值和次大值; 找出这四个数中的最大值作为总区间的最大值, 次大值作为总区间的次大值即可;
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 2e18;
typedef pair<int, int> PII;
int n, m, res = 1;
struct node{
int l, r;
int maxn, remaxn;
int mnum, rnum;
}tr[4 * N];
int p[N];
void pushup(node& root, node& left, node& right){
if(left.maxn == right.maxn){
root.maxn = left.maxn;
root.mnum = left.mnum + right.mnum;
if(left.remaxn == right.remaxn){
root.remaxn = left.remaxn;
root.rnum = left.rnum + right.rnum;
}
else if(left.remaxn > right.remaxn){
root.remaxn = left.remaxn;
root.rnum = left.rnum;
}
else if(left.remaxn < right.remaxn){
root.remaxn = right.remaxn;
root.rnum = right.rnum;
}
}
else if(left.maxn > right.maxn){
root.maxn = left.maxn;
root.mnum = left.mnum;
if(left.remaxn == right.maxn){
root.remaxn = left.remaxn;
root.rnum = left.rnum + right.mnum;
}
else if(left.remaxn > right.maxn){
root.remaxn = left.remaxn;
root.rnum = left.rnum;
}
else if(left.remaxn < right.maxn){
root.remaxn = right.maxn;
root.rnum = right.mnum;
}
}
else if(left.maxn < right.maxn){
root.maxn = right.maxn;
root.mnum = right.mnum;
if(left.maxn == right.remaxn){
root.remaxn = left.maxn;
root.rnum = left.mnum + right.rnum;
}
else if(left.maxn > right.remaxn){
root.remaxn = left.maxn;
root.rnum = left.mnum;
}
else if(left.maxn < right.remaxn){
root.remaxn = right.remaxn;
root.rnum = right.rnum;
}
}
}
void build(int u, int l, int r){
if(l == r) tr[u] = {l, r, p[l], 0, 1, 0};
else{
tr[u] = {l, r};
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
}
void modify(int u, int pos, int x){
if(tr[u].l == tr[u].r && tr[u].l == pos){
tr[u].maxn = x;
}
else{
int mid = tr[u].l + tr[u].r >> 1;
if(pos <= mid) modify(u << 1, pos, x);
else modify(u << 1 | 1, pos, x);
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
}
node query(int u, int l, int r){
if(tr[u].l >= l && tr[u].r <= r){
return tr[u];
}
else{
int mid = tr[u].l + tr[u].r >> 1;
node a, b;
int f1 = 0, f2 = 0;
if(l <= mid){
f1++;
a = query(u << 1, l, r);
}
if(r > mid){
f2++;
b = query(u << 1 | 1, l , r);
}
if(f1 && f2){
node c = {l, r};
pushup(c, a, b);
return c;
}
else{
if(f1) return a;
if(f2) return b;
}
}
}
signed main(){
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> p[i];
build(1, 1, n);
for(int i = 1; i <= m; i++){
int a, b, c;
cin >> a >> b >> c;
if(a == 1){
modify(1, b, c);
}
else{
cout << query(1, b, c).rnum << endl;
}
}
return 0;
}