当前位置: 首页 > news >正文

ABC417题解

A. A Substring

简单模拟即可

code
#include<bits/stdc++.h>
using namespace std;
string s;
int n,a,b;
int main(){cin >> n >> a >> b;cin >> s;for(int i = a; i < n-b; ++i){cout << s[i];}
}

B. Search and Delete

\(B\) 排序后简单模拟即可

code
#include<bits/stdc++.h>
using namespace std;
const int NN = 108;
int n,m;
int a[NN],b[NN];
int main(){cin >> n >> m;for(int i = 1; i <= n; ++i) cin >> a[i];for(int i = 1; i <= m; ++i) cin >> b[i];sort(b+1,b+1+m);for(int i = 1,j = 1; i <= n; ++i){while(j <= m && b[j] < a[i]) ++j;if(a[i] == b[j]){++j;}else{cout << a[i] << " ";}}
} 

C. Distance Indicators

tag: 思维题

这道题,让我们判定 \(j−i=A_i+A_j\) 的对数

我们先分离变量,发现就是找 \(A_i + i = A_j - j\) 的对数

我们从前往后扫,对于每个 \(A_i\),我们在 \(map\) 中查 \(A_i+i\) 并且将结果加入答案,然后我们向 \(map\) 中将 \(A_i-i\) 的出现次数 \(+1\)

code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int NN = 2e5 + 8;
int n;
ll ans;
int a[NN];
map<int,int> ps,mn;
int main(){cin >> n;for(int i = 1; i <= n; ++i){cin >> a[i];ans += ps[i-a[i]];ans += mn[a[i]+i];++ps[a[i]+i];++mn[i-a[i]];
//		cout << ans << endl;}cout << ans;}

bonus:满足 \(j-i < A_i+A_j\)\((i,j)\) 的对数?

答案

用树状数组即可

D. Takahashi's Expectation

tag:DP

害,线上同步考试的时候没做起,被 \(X_i\leq 10^9\) 卡了半天,结果发现 \(P_i,A_i,B_i\leq 500\)

显然如果心情值一开始大于 \(500\),那么一定会一点一点减少

我们可以用 \(DP\),设 \(f_{i,j}\) 表示若第 \(i\) 个礼物送出去之前还有 \(j\) 的心情值,到最后的心情值大小

\(DP\) 的转移显然是容易的,从最后倒推即可。

而一开始心情值大于 \(500\),我们只需要通过前缀和+二分,就可以找到第一次心情值小于等于 \(500\) 是在哪一次送出礼物之后,然后直接调用 \(DP\) 结果即可求得答案

E. A Path in A Dictionary

tag:贪心 搜索

给一张无向图,然后要求 \(U\to V\) 的字典序最小的路径

我们显然贪心地每一步都走编号更小的点,然后我们再加一个记忆化记录从一个点 \(x\) 出发,不能走回上一个来时的点 \(fa\) 能不能走到 \(V\) 即可,然后搜到的第一条路径就是答案

至于证明,显然先走向编号更大的点找到的路径字典序一定比走向编号更小的点的字典序更大

这样记忆化之后,我们保证了每条边只会走一次,复杂度 \(O(\sum m)\)

code
#include<bits/stdc++.h>
using namespace std;
const int NN = 1e3 + 8;vector<int> e[NN];
vector<int> sta;
bool fm[NN][NN];
bool vis[NN],gt;
void dfs(int u,int t,int fa){if(fm[fa][u]) return;sta.push_back(u);vis[u] = 1;if(u == t){gt = 1;return;}for(int i = 0; i < e[u].size(); ++i){int v = e[u][i];if(vis[v]) continue;dfs(v,t,u);if(gt) return;else fm[u][v] = 1;}sta.pop_back();vis[u] = 0;
}
int T,n,m,s,t;
int main(){cin >> T;while(T--){sta.clear();cin >> n >> m >> s >> t;gt = 0;for(int i = 1; i <= n; ++i) e[i].clear(),vis[i] = 0;for(int i = 1,u,v; i <= m; ++i){cin >> u >> v;e[u].push_back(v);e[v].push_back(u);}for(int i = 1; i <= n; ++i)sort(e[i].begin(),e[i].end());dfs(s,t,s);for(int i = 0; i < sta.size(); ++i){cout << sta[i] << ' ';}for(int i = 1; i <= n; ++i){for(int j = 0; j < e[i].size(); ++j)fm[i][e[i][j]] = 0;}cout << '\n';}
}

F. Random Gathering

tag:期望 线段树

去掉期望的外壳之后就是一道 区间平均的题

我们显然对于区间平均操作,可以用一个区间查询 + 区间赋值操作平替

这样之后,接下来的就是线段树的板子了

code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 998244353;
const int NN = 2e5 + 8;int n,m;
ll a[NN];inline ll ksm(ll x,ll k){ll ans = 1;while(k){if(k & 1) ans = ans * x % MOD;x = x * x % MOD;k >>= 1;}return ans;
}
inline ll inv(ll x){return ksm(x, MOD - 2);
}struct Seg{int l,r;ll sum,tag;#define l(x) tree[x].l#define r(x) tree[x].r#define ls(x) (x << 1)#define rs(x) (x << 1 | 1)#define sum(x) tree[x].sum#define tag(x) tree[x].tag
}tree[NN << 2];
void addlz(int x,ll num){sum(x) = (r(x) - l(x) + 1) * num % MOD;tag(x) = num;
}
void pushdown(int x){if(tag(x) != -1) addlz(ls(x),tag(x)), addlz(rs(x),tag(x));tag(x) = -1;
}
void pushup(int x){sum(x) = sum(ls(x)) + sum(rs(x));if(sum(x) >= MOD) sum(x) -= MOD;
}
void build(int x,int l,int r){l(x) = l;r(x) = r;if(l == r){addlz(x,a[l]);return;}tag(x) = -1;int mid = (l + r) / 2;build(ls(x),l,mid);build(rs(x),mid+1,r);pushup(x); 
}
ll query(int x,int l,int r){if(l <= l(x) && r(x) <= r){return sum(x);}pushdown(x);ll ans = 0,mid = (l(x) + r(x)) / 2;if(l <= mid) ans += query(ls(x),l,r);if(mid + 1 <= r) ans += query(rs(x),l,r);return ans % MOD;
}
void modify(int x,int l,int r,int num){if(l <= l(x) && r(x) <= r){addlz(x,num);return;}int mid = (l(x) + r(x)) / 2;pushdown(x);if(l <= mid) modify(ls(x),l,r,num);if(mid + 1 <= r) modify(rs(x),l,r,num);pushup(x);return;
}
void print(int x){if(l(x) == r(x)){printf("%lld ",sum(x));return;}pushdown(x);print(ls(x)); print(rs(x));return;
}int main(){ios::sync_with_stdio(false),cin.tie(0);cin >> n >> m;for(int i = 1; i <= n; ++i){cin >> a[i];}build(1,1,n);for(int i = 1,l,r; i <= m; ++i){cin >> l >> r;ll num = query(1,l,r) * inv(r-l+1) % MOD;
//		printf("%lld\n",num);modify(1,l,r,num);}print(1);return 0;
}
http://www.sczhlp.com/news/6304/

相关文章:

  • C++ 古法调试:使用 assert 宏
  • 美团
  • ubuntu扩盘,根目录/为例。 - try
  • 指针练习试题
  • 【从零开始实现stm32无刷电机FOC】尝试代码阅读
  • 暑假周总结3
  • 【自学嵌入式:51单片机】AD模数转换/DA数模转换(含SPI通信)
  • 2025.8.5 -「图论」
  • 暑假周总结2
  • 20250805-40
  • 1768. 交替合并字符串
  • 浏览器插件过度分享隐私问题剖析
  • 混合递归架构实现推理速度翻倍的技术解析
  • C++ RAII详解
  • RabbitMQ 网络分区
  • 深入解析:java设计模式 -【策略模式】
  • 20250805
  • OI 笑传 #6
  • 搜索旋转排序数组
  • 若依框架创建表结构异常
  • Koala 开源项目常见问题解决方案
  • 记得保存
  • 408-OS之多处理机
  • 百度Comate的AI编程工具小试
  • windows防火墙配置以及网络服务开放排查
  • 八股DAY1--MySQL面试题总结 - Charon
  • P9814 题解
  • 基础字符串算法及其运用
  • AUTO TECH 2025广州汽车内外饰展:解锁行业密码,展望未来出行美学 - 详解
  • 通过文件IO进行文件复制