908 字
2 分钟
Atcoder_Beginner_Contest_474(A~E题)
2026-09-11
浏览量 7 · 访客 5

壁纸链接
题目链接:https://atcoder.jp/contests/abc474/tasks

A - Not X#

只需要构造一个属于[1,3][1,3]且不等于XX的整数。若X=1X=1就输出22,否则输出11,两种情况都一定满足要求。时间复杂度和空间复杂度均为O(1)O(1)

void solve(){
int x; cin >> x;
if(x == 2) cout << 1 << '\n';
if(x == 3) cout << 1 << '\n';
if(x == 1) cout << 2 << '\n';
}

B - Exit Order#

按照编号每1010个元素划分一组,第ii个位置应当由第i110+1\lfloor\frac{i-1}{10}\rfloor+1组中的元素占据。该组允许出现的最大编号为 (i110+1)×10\left(\lfloor\frac{i-1}{10}\rfloor+1\right)\times10。 因此依次检查PiP_i是否超过这个上界即可。虽然代码没有显式检查当前组的下界,但PP是一个排列:前面的完整位置组已经用完了所有更小编号,所以当前元素不可能属于更早的组。若所有元素均未超过对应上界,分组顺序就是合法的。时间复杂度为O(N)O(N),额外空间复杂度为O(1)O(1)

void solve(){
int n; cin >> n;
bool f = true;
for(int i = 1; i <= n;i++){
int x; cin >> x;
int val = ((i - 1) / 10 + 1) * 10;
if(x > val) f = false;
}
if(f) cout << "Yes" << '\n';
else cout << "No" << '\n';
}

C - Remove and Append#

直接在数组中删除元素会引起整体移动,单次操作最坏需要O(N)O(N)。由于PP11NN的排列,可以直接以元素值作为下标,用pre[x]pre[x]nxt[x]nxt[x]分别记录xx的前驱和后继,从而用数组模拟双向链表;同时维护链表的headheadtailtail。 将xx移动到末尾时,先用它的前驱和后继相互连接。若xx原本是头节点,则改为更新headhead;然后令原来的tailtail指向xx,并将xx设为新的尾节点。若xx已经位于末尾,序列不会改变,可以直接跳过。每次修改只涉及常数个指针,全部询问处理完后从headhead沿nxtnxt遍历即可恢复最终排列。 建立链表和输出排列均为O(N)O(N),处理询问为O(Q)O(Q),总时间复杂度为O(N+Q)O(N+Q),空间复杂度为O(N)O(N)

void solve(){
int n, q;
cin >> n >> q;
vector<int> pre(n + 1), nxt(n + 1);
vector<int> a(n + 1);
int head = -1, tail = -1;
for(int i = 1; i <= n;i++){
cin >> a[i];
if(i == 1) head = a[i];
if(i > 1){
pre[a[i]] = a[i - 1];
nxt[a[i - 1]] = a[i];
}
}
tail = a[n];
for(int i = 1; i <= q;i++){
int x; cin >> x;
if(tail == x) continue;
if(pre[x] != 0) nxt[pre[x]] = nxt[x];
else head = nxt[x];
if(nxt[x] != 0) pre[nxt[x]] = pre[x];
nxt[tail] = x;
pre[x] = tail;
nxt[x] = 0;
tail = x;
}
int cur = head;
while(cur){
cout << cur << " ";
cur = nxt[cur];
}
cout << '\n';
}

D - Outweigh#

ci=AiBic_i=A_i-B_i,要求等价于构造正整数权值,使 i=1NciWi>0\sum_{i=1}^{N}c_iW_i>0。 若所有ci0c_i\leq0,由于每个WiW_i都必须为正数,上式不可能严格大于00,因此无解。 若存在ci>0c_i>0,则把所有正系数对应的权值设为101810^{18},其余权值设为11。正系数均为整数,所以正贡献至少为101810^{18};另一方面,负系数的绝对值小于10910^9,且N105N\leq10^5,全部负贡献的绝对值小于101410^{14}。因此正贡献一定严格大于负贡献,构造合法。 只需遍历数组判断是否存在正系数并输出对应权值,时间复杂度为O(N)O(N),空间复杂度为O(N)O(N)

void solve(){
int n; cin >> n;
vector<ll> a(n + 1), b(n + 1);
vector<ll> c(n + 1);
bool has_z = false;
vector<int> z;
for(int i = 1; i <= n;i++) cin >> a[i];
for(int i = 1; i <= n;i++) cin >> b[i];
for(int i = 1; i <= n;i++){
c[i] = a[i] - b[i];
if(c[i] > 0) {has_z = true; z.push_back(i);}
}
vector<ll> ans(n + 1);
if(!has_z) {cout << "No" << '\n'; return;}
cout << "Yes" << '\n';
for(auto &it : z){
ans[it] = (ll)1e18;
}
for(int i = 1; i <= n;i++){
if(ans[i] == 0) ans[i] = 1;
cout << ans[i] << " ";
}
}

E - One Time Coupon#

设最终有ii种商品使用优惠券完成至少一次购买,其余NiN-i种商品按AjA_j购买。先假设所有商品都按原价购买,基础费用为base=Ajbase=\sum A_j。把商品jj改为使用优惠券后,费用变化量为BjAjB_j-A_j。因此当ii固定时,应选择变化量最小的ii种商品;将所有BjAjB_j-A_j排序后取前缀和即可。 按原价购买一次会产生一张优惠券,而使用优惠券购买会消耗一张。上述方案产生NiN-i张、消耗ii张优惠券。当iNii\leq N-i时,不需要额外购买;当i>Nii>N-i时,还缺少2iN2i-N张优惠券。每张缺少的优惠券都可以通过额外按原价购买任意商品获得,而重复购买的最低单价是minAj\min A_j,所以补充费用为 max(0,2iN)×minAj\max(0,2i-N)\times\min A_j。 枚举i=0,1,,Ni=0,1,\ldots,N,维护排序后变化量的前缀和,并对 base+j=1idiffj+max(0,2iN)×minAjbase+\sum_{j=1}^{i}diff_j+\max(0,2i-N)\times\min A_j 取最小值。排序占用O(NlogN)O(N\log N)时间,枚举占用O(N)O(N)时间,空间复杂度为O(N)O(N)

void solve(){
int n; cin >> n;
ll base = 0;
ll mia = LLONG_MAX;
vector<ll> diff;
for(int i = 1; i <= n;i++){
ll a, b; cin >> a >> b;
base += a;
mia = min(mia, a);
diff.push_back(b - a);
}
sort(diff.begin(), diff.end());
ll ans = base, cur = base;
for(int i = 1; i <= n;i++){
cur += diff[i - 1];
ll extra = max(0, 2 * i - n);
ans = min(ans, cur + extra * mia);
}
cout << ans << '\n';
}

模板:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
#define mod 998244353
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll fast_pow(ll a, ll b, ll MOD){
ll ans = 1;
while(b){
if(b & 1) ans = (ans * a) % MOD;
b >>= 1;
a = (a * a) % MOD;
}
return ans;
}
vector<ll> get_inverse(ll n, ll MOD){
vector<ll> inverse(n + 1, 0);
inverse[1] = 1;
for(int i = 2; i <= n;i++){
inverse[i] = MOD - (MOD / i) * inverse[MOD % i] % MOD;
}
return inverse;
}
struct DSU{
vector<int> fa, sz;
DSU(int n){
fa.resize(n + 1);
sz.resize(n + 1, 1);
for(int i = 1; i <= n;i++){
fa[i] = i;
}
}
int find(int x){
if(fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
bool merge(int x, int y){
x = find(x);
y = find(y);
if(x == y) return false;
if(sz[x] > sz[y]) swap(x, y);
fa[y] = x;
sz[x] += sz[y];
return true;
}
};
void solve(){
}
int main(){
ios::sync_with_stdio(false),
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
//cin >> _;
while(_--){
solve();
}
return 0;
}
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Atcoder_Beginner_Contest_474(A~E题)
https://mkrari.cn/posts/abc_474/
作者
Mkrari
发布于
2026-09-11
许可协议
CC BY-NC-SA 4.0