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;
}
posted @ 2025-07-07 13:15  Li_Yujia  阅读(37)  评论(0)    收藏  举报