[题解]AtCoder Beginner Contest 406(ABC406) A~F
因为上线时间有限所以补题和题解都延误了(^^;
写得很急,如有错误/不清晰的点请在评论区提出。
A - Not Acceptable
见代码。时间复杂度\(O(1)\)。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int a,b,c,d;
signed main(){
cin>>a>>b>>c>>d;
if(a>c) cout<<"Yes\n";
else if(a==c&&b>d) cout<<"Yes\n";
else cout<<"No\n";
return 0;
}
B - Product Calculator
设当前屏幕上的数字为\(fac\),要乘的数是\(a\),则:
如果\(fac\times a\ge 10^k\),则将\(fac\)置为\(1\);否则将\(fac\)累乘\(a\)。
\(fac\times a\)可能会爆long long,可以使用__int128,或者可以转化一下条件:
- \(fac\times a\ge 10^k\iff a\ge \lceil\frac{10^k}{fac}\rceil\)。
时间复杂度\(O(n)\)。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,k,fac=1;
signed main(){
cin>>n>>k;
int t=1;
for(int i=1;i<=k;i++) t*=10;
while(n--){
int a;
cin>>a;
if(a>=(t-1)/fac+1) fac=1;
else fac*=a;
}
cout<<fac<<"\n";
return 0;
}
C - ~
显然峰值和谷值是交替出现的。
我们要找到的就是一个区间,使得这个区间:
- 恰好有\(1\)个峰值和\(1\)个谷值。
- 峰值在谷值前。
- 区间头尾均不是峰值/谷值。
定义\(nxt[i]\)为\(a[i\sim n]\)中第一个峰/谷的位置。
枚举所有\(i\)使得\(a[i]<a[i+1]\),定义\(n_1=nxt[i+1],n_2=nxt[n_1+1],n_3=nxt[n_2+1]\)。
如果\(n_1,n_2\)都存在,则:
- 如果\(n_3\)存在,则累加\(n_3-n_2\)的贡献。
- 如果\(n_3\)不存在,则累加\(n-n_2\)的贡献。
时间复杂度\(O(n)\)。
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define N 300010
using namespace std;
int n,a[N],b[N],nxt[N],pre[N],ans;
signed main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=2;i<n;i++) if((a[i]>a[i-1]&&a[i]>a[i+1])||(a[i]<a[i-1]&&a[i]<a[i+1])) b[i]=1;
for(int i=1;i<=n;i++) pre[i]=(b[i]?i:pre[i-1]);
for(int i=n;i>=1;i--) nxt[i]=(b[i]?i:nxt[i+1]);
for(int i=1;i<n;i++){
if(a[i]<a[i+1]){
int n1=nxt[i+1],n2=nxt[n1+1],n3=nxt[n2+1];
if(n1&&n2) ans+=(n3?n3-n2:n-n2);
}
}
cout<<ans<<"\n";
return 0;
}
D - Garbage Removal
赛时思路(稍有修改):为行和列各开一个
set存里面的垃圾的坐标\((x,y)\),每处理一个行的操作,就遍历该行的垃圾,并在其所在列中删除它。列同理。为了方便查找,代码将\((x,y)\)压成一个整数了。
时间复杂度\(O(n+m+k+q)\)。
题解思路:同一行/列的询问,从第\(2\)次开始就是\(0\)不变了。所以为行和列各开一个桶来统计该行/列是否被查询过,如果查询过直接输出\(0\),否则遍历该行/列的垃圾,如果没有被清除,则产生\(1\)的贡献,并标记该垃圾已被清除。
由于每行、每列的垃圾最多被遍历\(1\)次,所以时间复杂度为\(O(n+m+k+q)\)。
赛时思路
#include<bits/stdc++.h>
#define int long long
#define N 200010
using namespace std;
int n,m,k,q;
unordered_map<int> hang[N],lie[N];
signed main(){
cin>>n>>m>>k;
while(k--){
int x,y;
cin>>x>>y;
hang[x].insert(x*N+y),lie[y].insert(x*N+y);
}
cin>>q;
while(q--){
int op,x;
cin>>op>>x;
if(op==1){
cout<<hang[x].size()<<"\n";
for(auto i:hang[x]) lie[i%N].erase(i);
hang[x].clear();
}else{
cout<<lie[x].size()<<"\n";
for(auto i:lie[x]) hang[i/N].erase(i);
lie[x].clear();
}
}
return 0;
}
题解代码见https://atcoder.jp/contests/abc406/editorial/13053。
E - Popcount Sum 3
数位dp,下文使用DFS实现,规定最低位为\(1\)。
由于要对满足条件的数求和,所以如果我们搜索到最后再统计贡献的话,将很难记忆化。因为就算两个搜索的状态“当前的数位”和“到目前为止\(1\)的个数”都相同,由于已经填好的数位不同,两个状态的答案也一定不同。但是这两个状态往后填写的情况是完全相同的。
所以我们不妨修改策略,让每个状态仅统计:
- \(sum\):其搜索子树中所有答案 从当前数位到最低位的子串 之和。
- \(cnt\):其搜索子树中的答案个数。
\(sum\)的定义说明每个状态仅需关注它后面所填的值,不需要管之前填写的内容。与CF1073E Segment Sum(题解)这道题非常相似,可以类比一下两题的做法。
假设当前填到第\(pos\)位,则有转移:
\]
最后输出\(sum[root]\)即可。
可以使用\(f[pos][pc]\)来记忆化,其中\(pc\)是填到目前\(1\)的个数。
时间复杂度\(O(|\Sigma|\times \lg n\times k)\)。其中\(|\Sigma|=2\),表示字符集大小。
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define mod 998244353
#define K 70
using namespace std;
int t,n,k,a[K];
bitset<K> fv[K];
pair<int,int> f[K][K];
//first表示cnt,second表示sum
pair<int,int> dfs(int pos,bool limit,int pc){
if(pc>k) return {0,0};
if(!pos) return {(pc==k),0};
if(!limit&&fv[pos][pc]) return f[pos][pc];
int rig=limit?a[pos]:1;
pair<int,int> ans{0,0};
for(int i=0;i<=rig;i++){
auto res=dfs(pos-1,limit&&i==rig,pc+i);
(ans.second+=res.second)%=mod;
(ans.second+=i*(1ll<<(pos-1))%mod*res.first%mod)%=mod;
(ans.first+=res.first)%=mod;
}
if(!limit) fv[pos][pc]=1,f[pos][pc]=ans;
return ans;
}
int solve(int x){
for(int i=0;i<K;i++) fv[i]=0;
int len=0;
while(x) a[++len]=x&1,x>>=1;
return dfs(len,1,0).second;
}
signed main(){
cin>>t;
while(t--){
cin>>n>>k;
cout<<solve(n)<<"\n";
}
return 0;
}
F - Compare Tree Weights
核心操作在于单点修改权值以及查询子树和。
我们按DFS序给每个节点重新编号,容易发现一个子树中节点的DFS序是连续的,所以可以放到树状数组/线段树上操作。
其实就是把树剖模板题里“子树操作”弱化后搬到这来了。
代码的时间复杂度\(O((n+q)\log n)\),树状数组初始化优化一下可以做到\(O(n+q\log n)\)。
点击查看代码
#include<bits/stdc++.h>
#define N 300010
using namespace std;
int n,q,tim,dfn[N],siz[N],u[N],v[N],dep[N];
vector<int> G[N];
inline int lowbit(int x){return x&-x;}
struct BIT{
int s[N];
void add(int x,int k){while(x<=n) s[x]+=k,x+=lowbit(x);}
int query(int x){int ans=0;while(x) ans+=s[x],x-=lowbit(x);return ans;}
int query(int l,int r){return query(r)-query(l-1);}
}bit;
void dfs(int u,int fa){
dfn[u]=++tim,siz[u]=1,dep[u]=dep[fa]+1;
for(int i:G[u]) if(i!=fa) dfs(i,u),siz[u]+=siz[i];
}
void add(int u,int v){G[u].emplace_back(v);}
signed main(){
cin>>n;
for(int i=1;i<n;i++) cin>>u[i]>>v[i],add(u[i],v[i]),add(v[i],u[i]);
dfs(1,0);
for(int i=1;i<n;i++) if(dep[u[i]]<dep[v[i]]) swap(u[i],v[i]);
for(int i=1;i<=n;i++) bit.add(i,1);
cin>>q;
while(q--){
int o,x,y;
cin>>o;
if(o==1){
cin>>x>>y,bit.add(dfn[x],y);
}else{
cin>>x;
int s=bit.query(n),t=bit.query(dfn[u[x]],dfn[u[x]]+siz[u[x]]-1);
cout<<abs(2*t-s)<<"\n";
}
}
return 0;
}
[题解]AtCoder Beginner Contest 406(ABC406) A~F的更多相关文章
- 题解 AtCoder Beginner Contest 168
小兔的话 欢迎大家在评论区留言哦~ AtCoder Beginner Contest 168 A - ∴ (Therefore) B - ... (Triple Dots) C - : (Colon) ...
- 【AtCoder Beginner Contest 181】A~F题解
越学越菜系列 于2020.11.2,我绿了(错乱) A - Heavy Rotation 签到题,奇数Black,偶数White. code: #include<bits/stdc++.h> ...
- AtCoder Beginner Contest 127 D,E,F
D Integer Cards 题意:先给出n个数字,然后可以有m次操作,每次操作以数字对(x,y)表示最多能选x个数字把它变成y,问经历m次操作后n个数字和最大为多少? 解法:一个明显正确的做法是: ...
- [题解] Atcoder Beginner Contest ABC 270 G Ex 题解
点我看题 G - Sequence in mod P 稍微观察一下就会发现,进行x次操作后的结果是\(A^xS+(1+\cdots +A^{x-1})B\).如果没有右边那一坨关于B的东西,那我们要求 ...
- [题解] Atcoder Beginner Contest ABC 265 Ex No-capture Lance Game DP,二维FFT
题目 首先明确先手的棋子是往左走的,将其称为棋子1:后手的棋子是往右走的,将其称为棋子2. 如果有一些行满足1在2右边,也就是面对面,那其实就是一个nim,每一行都是一堆石子,数量是两个棋子之间的空格 ...
- AtCoder Beginner Contest 238 A - F 题解
AtCoder Beginner Contest 238 \(A - F\) 题解 A - Exponential or Quadratic 题意 判断 \(2^n > n^2\)是否成立? S ...
- AtCoder Beginner Contest 137 F
AtCoder Beginner Contest 137 F 数论鬼题(虽然不算特别数论) 希望你在浏览这篇题解前已经知道了费马小定理 利用用费马小定理构造函数\(g(x)=(x-i)^{P-1}\) ...
- AtCoder Beginner Contest 154 题解
人生第一场 AtCoder,纪念一下 话说年后的 AtCoder 比赛怎么这么少啊(大雾 AtCoder Beginner Contest 154 题解 A - Remaining Balls We ...
- AtCoder Beginner Contest 153 题解
目录 AtCoder Beginner Contest 153 题解 A - Serval vs Monster 题意 做法 程序 B - Common Raccoon vs Monster 题意 做 ...
- AtCoder Beginner Contest 177 题解
AtCoder Beginner Contest 177 题解 目录 AtCoder Beginner Contest 177 题解 A - Don't be late B - Substring C ...
随机推荐
- 聊一聊 .NET在Linux下的IO多路复用select和epoll
一:背景 1. 讲故事 在windows平台上,相信很多人都知道.NET异步机制是借助了Windows自带的 IO完成端口 实现的异步交互,那在 Linux 下.NET 又是怎么玩的呢?主要还是传统的 ...
- 设置java程序的守护进程
1.在服务器执行:crontab -e 命令 2.在出现的界面编写cron表达式 3.编写guard_java_extbork.sh脚本 #!/bin/bash source /etc/profil ...
- Kubernetes二进制文件下载链接
这里,我们下载kubernetes的二进制文件在其官网下载即可: 具体链接:https://kubernetes.io/docs/setup/release/notes/
- 5分钟搞定!最全Dokploy部署n8n教程
最近n8n太火了,官方的次数有限,很多人有自己部署的需求.但常规的部署方案总是耗时耗力,拖慢整个开发节奏. 今天我分享一个我自己实践总结的Dokploy部署n8n的超详细教程,帮助你在短短几分钟内完成 ...
- .NET Core如何通过认证机制访问Kafka?
大家好,我是Edison. 最近有一个ASP.NET Core使用认证机制访问Kafka的需求,加之我们又使用了CAP这个开源项目使用的Kafka,于是网上寻找了一番发现对应资料太少,于是调查了一番, ...
- Viual Studio 共享组件、工具和SDK的位置不能更改 解决方案
https://blog.csdn.net/weixin_41923658/article/details/103214742 找到电脑上 VS 的注册表,删除共享组件.工具和 SDK 的注册表: ...
- C# 泛型对象转Get请求参数
/// <summary> /// 对象转Get请求参数 /// </summary> /// <returns>< ...
- C#源生成器:让你的代码飞起来的黑科技
大家好,我是token.今天想和大家聊聊C#源生成器这个神奇的技术. 说起源生成器,可能很多同学会想:又是什么新的轮子?我反射用得好好的,为什么要学这个?别急,看完这篇文章,你就会发现源生成器简直是性 ...
- C++求最长的一条食物链的长度。DFS深度优先算法
题目描述 如图所示为某生态系统的食物网示意图,据图回答第一小题. 1. 数一数,在这个食物网中最长的食物链包含的物种数是 ( ) ...... 现在给你 n 个物种和 m 条能量流动关系,求其中的食物 ...
- 从崩溃到稳定:前端开发者必学的 Node.js 守护进程实战指南
本文原创首发于公众号[我做开发那些年]与网站[乔文小屋],现同步转载至本平台,点击阅读原文 声明:如需转载本文至其他平台,请注明文章来源及公众号信息,感谢您对原创内容的尊重与支持! 说到守护进程,绝大 ...