Denso Create Programming Contest 2025(AtCoder Beginner Contest 413)A-F题解
A
略
B
略
C - Large Queue
题意:
两种操作,第一种:将x拷贝c份放置于a的末尾。第二种:查询a的前k个元素的值。
思路:
考虑维护两个双端队列队列num和val,分别代表元素个数以及数量,对于每次操作,如果当前k值大于num队头元素,则答案增加num.front()\(\times\)val.front ()。否则此时num头出队,入队新的个数。
代码
#include<bits/stdc++.h>
#define ll long long
#define ce cerr
#define ull unsigned long long
#define lll __int128
using namespace std;
const int inf = 0x3f3f3f3f;
const ll iinf = 1e18;
//cin.ignore(std::numeric_limits< streamsize >::max(), '\n');
int t;
void print(__int128 x) {
if (x < 0) {
cout << '-';
x = -x;
}
if (x > 9) {
print(x / 10);
}
cout << (char)('0' + x % 10);
}
void solve() {
int q;
cin >> q;
deque<ll> num;
deque<ll> val;
while (q --) {
int op;
cin >> op;
if (op == 1) {
int c, x;
cin >> c >> x;
num.push_back (c);
val.push_back (x);
}else {
ll k;
cin >> k;
lll res = 0;
while (!num.empty () && k >= num.front ()) {
res += num.front () * val.front ();
k -= num.front ();
num.pop_front ();
val.pop_front ();
}
if (k) {
res += k * val.front ();
auto it = num.front ();
num.pop_front ();
num.push_front (it - k);
}
print (res);
cout << "\n";
}
}
}
int main() {
ios::sync_with_stdio (false);
cin.tie(NULL);
cout.tie(NULL);
t = 1;
//cin >> t;
while (t --) {
solve();
}
return 0;
}
D - Make Geometric Sequence
题意:
给定一个序列,判断该序列的所有元素能否由某一元素乘一个固定值q得到。
思路:
分两种情况讨论
①序列元素均为同号:此时q值一定为正数,将序列排序后直接判断即可。
②序列元素均为异号:此时q值一定为负数,观察发现,序列一定按照元素绝对值顺序排列,故将正元素和负元素按此规则排序,判断即可
(写的比较丑陋,其实直接自定义sort即可(return abs (x) < abs (y)) ,此时需要特判为1和-1的情况,发现正元素和负数素的个数相差一定小于等于2)
判断是否为等比的条件: a[x - 1] \(\times\) a[x + 1] = a[x]
代码
#include<bits/stdc++.h>
#define ll long long
#define ce cerr
#define ull unsigned long long
#define lll __int128
using namespace std;
const int inf = 0x3f3f3f3f;
const ll iinf = 1e18;
//cin.ignore(std::numeric_limits< streamsize >::max(), '\n');
int t;
void solve() {
int n;
cin >> n;
vector<ll> a (n + 1);
vector<ll> pos;
vector<ll> neg;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
if (a[i] < 0) {
neg.push_back (a[i]);
}else{
pos.push_back (a[i]);
}
}
sort (pos.begin (), pos.end ());
sort (neg.begin (), neg.end (), greater<ll> ());
if (!neg.empty () && !pos.empty ()) {
int n2 = neg.size ();
int n1 = pos.size ();
vector<ll> temp;
if (abs (n1 - n2) >= 2) {
cout << "No" << "\n";
}else{
vector<ll> temp;
bool flag1 = 1;
bool flag2 = 1;
int idx = 0;
for (int i = 0; i < n1; ++i) {
temp.push_back (pos[i]);
if (idx < n2) {
temp.push_back (neg[idx ++]);
}
}
if (idx != n2) {
temp.push_back (neg[idx]);
}
for (int i = 1; i < temp.size () - 1; ++i) {
if (temp[i] * temp[i] != temp[i - 1] * temp[i + 1]) {
flag1 = false;
break;
}
}
vector<ll> temp2;
idx = 0;
for (int i = 0; i < n2; ++i) {
temp2.push_back (neg[i]);
if (idx < n1) {
temp2.push_back (pos[idx ++]);
}
}
if (idx != n1) {
temp2.push_back (pos[idx]);
}
for (int i = 1; i < temp2.size () - 1; ++i) {
if (temp2[i] * temp2[i] != temp2[i - 1] * temp2[i + 1]) {
flag2 = false;
break;
}
}
if (flag1 || flag2) {
cout << "Yes" << "\n";
}else{
cout << "No" << "\n";
}
}
}else{
sort (a.begin () + 1, a.end ());
for (int i = 2; i < n; ++i) {
if (a[i] * a[i] != a[i - 1] * a[i + 1]) {
cout << "No" << "\n";
return ;
}
}
cout << "Yes" << "\n";
}
}
int main() {
ios::sync_with_stdio (false);
cin.tie(NULL);
cout.tie(NULL);
t = 1;
cin >> t;
while (t --) {
solve();
}
return 0;
}
E - Reverse 2^i
题意:
以类似线段树分块的限制进行区间翻转,求序列翻转后的字典序最小值
思路:
分治思想,递归进入每一层函数空间,\(最优解=左序列最优解+右序列最优解\)
代码
#include<bits/stdc++.h>
#define ll long long
#define ce cerr
#define ull unsigned long long
#define lll __int128
using namespace std;
const int inf = 0x3f3f3f3f;
const ll iinf = 1e18;
const int N = (1 << 19);
//cin.ignore(std::numeric_limits< streamsize >::max(), '\n');
int t;
int A[N];
bool check (vector<int> a, vector<int> b) {
for (int i = 0; i < a.size (); ++i) {
if (a[i] > b[i]) {
return 1;
}else if (a[i] < b[i]) {
return 0;
}
}
return 0;
}
vector<int> dfs (int x, int y) {
if (y - x == 1) {
vector<int> res;
if (A[x] < A[y]) {
res.push_back (A[x]);
res.push_back (A[y]);
}else{
res.push_back (A[y]);
res.push_back (A[x]);
}
return res;
}
int mid = x + y >> 1;
vector<int> left = dfs (x, mid);
vector<int> right = dfs (mid + 1, y);
if (check (left, right)) {
vector<int> res (right.begin (), right.end ());
res.insert (res.end (), left.begin (), left.end ());
return res;
}
vector<int> res (left.begin (), left.end ());
res.insert (res.end (), right.begin (), right.end ());
return res;
}
void solve() {
int n;
cin >> n;
for (int i = 1; i <= (1 << n); ++i) {
cin >> A[i];
}
vector<int> res;
res = dfs (1, 1 << n);
for (auto i : res) {
cout << i << " ";
}cout << "\n";
}
int main() {
ios::sync_with_stdio (false);
cin.tie(NULL);
cout.tie(NULL);
t = 1;
cin >> t;
while (t --) {
solve();
}
return 0;
}
F - No Passage
题意:
给定一个二维数组,对于每一个方格为起点,每次选定一个方向,阻止其向此方向转移,问每一个方格到达target的最小次数是多少
思路:
发现对于一个方格,只要上下左右四格中至少有两格能够到达target,则此方格必然能够到达target。故考虑bfs,target点所需移动次数为0,将target点入队。对于每一个队头,并将其影响的上下左右四格次数+1,若方格影响次数=2,则将方格的次数设为此时的队头的移动次数+1,将此方格入队。
代码
#include<bits/stdc++.h>
#define ll long long
#define ce cerr
#define ull unsigned long long
#define lll __int128
using namespace std;
const int inf = 0x3f3f3f3f;
const ll iinf = 1e18;
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, -1, 0, 1};
//cin.ignore(std::numeric_limits< streamsize >::max(), '\n');
int t;
int h, w, k;
struct node {
int x, y, value;
};
bool isvalid (int x, int y) {
return x >= 1 && x <= h && y >= 1 && y <= w;
}
void solve() {
cin >> h >> w >> k;
vector<vector<int> > a (h + 1, vector<int> (w + 1));
vector<vector<int> > cnt (h + 1, vector<int> (w + 1));
queue<node> que;
for (int i = 1; i <= k; ++i) {
int x, y;
cin >> x >> y;
que.push ({x, y, 0});
cnt[x][y] = 2;
}
while (!que.empty ()) {
auto it = que.front ();
que.pop ();
for (int i = 0; i < 4; ++i) {
int xx = dx[i] + it.x;
int yy = dy[i] + it.y;
if (isvalid (xx, yy)) {
if (cnt[xx][yy] == 2) {
continue;
}
cnt[xx][yy] ++;
if (cnt[xx][yy] == 2) {
a[xx][yy] = it.value + 1;
que.push ({xx, yy, a[xx][yy]});
}
}
}
}
ll res = 0;
for (int i = 1; i <= h; ++i) {
for (int j = 1; j <= w; ++j) {
res += a[i][j];
}
}
cout << res << "\n";
}
int main() {
ios::sync_with_stdio (false);
cin.tie(NULL);
cout.tie(NULL);
t = 1;
//cin >> t;
while (t --) {
solve();
}
return 0;
}