[题解]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 ...
随机推荐
- buck参数工具分享
工具链接:https://cnblogs-img.oss-cn-hangzhou.aliyuncs.com/docs/buck.xls
- 【中英】【吴恩达课后测验】Course 1 - 神经网络和深度学习 - 第四周测验
[中英][吴恩达课后测验]Course 1 - 神经网络和深度学习 - 第四周测验 上一篇:[课程1 - 第三周编程作业]※※※※※ [回到目录]※※※※※下一篇:[课程1 - 第四周编程作业] 第4 ...
- 杂七杂八系列----C#代码如何影响CPU缓存速度?
CPU与RAM的隔阂 CPU与RAM是两个独立的硬件,并非集成在一起.所以他们两个之间一定会存在一个连接的桥梁,这个桥梁的名字叫做内存总线. 内存总线由三部分组成: 地址总线(Address Bus) ...
- cookie,session以及application的比较
cookie工作原理: cookie代码: 1 @WebServlet(value = "/cookie",name = "CookieServlet") 2 ...
- 边学边练,福利无限 —— OceanBase DBA 实战营(第一季)火热进行中!
首先为大家推荐这个 OceanBase 开源负责人老纪的公众号 "老纪的技术唠嗑局",会持续更新和 OceanBase 相关的各种技术内容.欢迎感兴趣的朋友们关注! 活动背景 20 ...
- veRL代码阅读-1.论文原理
总览 主要以PPO为基础来学习VeRL的整体训练流程. 在PPO里主要有4个模型: Actor Model: 要训练的目标模型. Critic Model: 用于在RL训练中评估总收益, 在训练过程中 ...
- 什么是仿真软件?推荐几个简单易上手的几款CAE软件!
什么是仿真软件?仿真软件(CAE软件)是一种用于模拟和模仿真实世界系统或过程的计算机程序.这些软件可以用来模拟物理系统.工程系统.商业流程等各种领域的系统.通过仿真软件,用户可以对系统进行实时的模拟. ...
- 修复windows组策略管理器
问题 windows自带的组策略管理器损坏,无法打开 修复 把如下代码复制到txt中,保存修改后缀名为bat文件,用管理员运行此文件修复即可 rd /s /q "%windir%\Syste ...
- windows10搭建gitlab服务器
gitlab服务器没有win运行环境,所以需要先搭建个虚拟机:windows10+VMware(Centos7) +gitlab+局域网其他电脑访问 一:VMware 安装,网上找找有安装教程 二:虚 ...
- sublime text 2 snippet 设置
1.标准文件写法 <snippet> <content><![CDATA[ 你需要插入的代码片段${1:name} ]]></content> < ...