因为上线时间有限所以补题和题解都延误了(^^;

写得很急,如有错误/不清晰的点请在评论区提出。

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\)。

这些是我的数位dp笔记:上篇下篇EX(未发布)

由于要对满足条件的数求和,所以如果我们搜索到最后再统计贡献的话,将很难记忆化。因为就算两个搜索的状态“当前的数位”和“到目前为止\(1\)的个数”都相同,由于已经填好的数位不同,两个状态的答案也一定不同。但是这两个状态往后填写的情况是完全相同的。

所以我们不妨修改策略,让每个状态仅统计:

  • \(sum\):其搜索子树中所有答案 从当前数位到最低位的子串 之和。
  • \(cnt\):其搜索子树中的答案个数。

\(sum\)的定义说明每个状态仅需关注它后面所填的值,不需要管之前填写的内容。与CF1073E Segment Sum题解)这道题非常相似,可以类比一下两题的做法。

假设当前填到第\(pos\)位,则有转移:

\[\large sum[u]=\sum\limits_{i\in son[u],第pos位填w} sum[i]+w\times cnt[i]\times 2^{pos-1}
\]

最后输出\(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的更多相关文章

  1. 题解 AtCoder Beginner Contest 168

    小兔的话 欢迎大家在评论区留言哦~ AtCoder Beginner Contest 168 A - ∴ (Therefore) B - ... (Triple Dots) C - : (Colon) ...

  2. 【AtCoder Beginner Contest 181】A~F题解

    越学越菜系列 于2020.11.2,我绿了(错乱) A - Heavy Rotation 签到题,奇数Black,偶数White. code: #include<bits/stdc++.h> ...

  3. AtCoder Beginner Contest 127 D,E,F

    D Integer Cards 题意:先给出n个数字,然后可以有m次操作,每次操作以数字对(x,y)表示最多能选x个数字把它变成y,问经历m次操作后n个数字和最大为多少? 解法:一个明显正确的做法是: ...

  4. [题解] Atcoder Beginner Contest ABC 270 G Ex 题解

    点我看题 G - Sequence in mod P 稍微观察一下就会发现,进行x次操作后的结果是\(A^xS+(1+\cdots +A^{x-1})B\).如果没有右边那一坨关于B的东西,那我们要求 ...

  5. [题解] Atcoder Beginner Contest ABC 265 Ex No-capture Lance Game DP,二维FFT

    题目 首先明确先手的棋子是往左走的,将其称为棋子1:后手的棋子是往右走的,将其称为棋子2. 如果有一些行满足1在2右边,也就是面对面,那其实就是一个nim,每一行都是一堆石子,数量是两个棋子之间的空格 ...

  6. AtCoder Beginner Contest 238 A - F 题解

    AtCoder Beginner Contest 238 \(A - F\) 题解 A - Exponential or Quadratic 题意 判断 \(2^n > n^2\)是否成立? S ...

  7. AtCoder Beginner Contest 137 F

    AtCoder Beginner Contest 137 F 数论鬼题(虽然不算特别数论) 希望你在浏览这篇题解前已经知道了费马小定理 利用用费马小定理构造函数\(g(x)=(x-i)^{P-1}\) ...

  8. AtCoder Beginner Contest 154 题解

    人生第一场 AtCoder,纪念一下 话说年后的 AtCoder 比赛怎么这么少啊(大雾 AtCoder Beginner Contest 154 题解 A - Remaining Balls We ...

  9. AtCoder Beginner Contest 153 题解

    目录 AtCoder Beginner Contest 153 题解 A - Serval vs Monster 题意 做法 程序 B - Common Raccoon vs Monster 题意 做 ...

  10. AtCoder Beginner Contest 177 题解

    AtCoder Beginner Contest 177 题解 目录 AtCoder Beginner Contest 177 题解 A - Don't be late B - Substring C ...

随机推荐

  1. 聊一聊 .NET在Linux下的IO多路复用select和epoll

    一:背景 1. 讲故事 在windows平台上,相信很多人都知道.NET异步机制是借助了Windows自带的 IO完成端口 实现的异步交互,那在 Linux 下.NET 又是怎么玩的呢?主要还是传统的 ...

  2. 设置java程序的守护进程

    1.在服务器执行:crontab -e 命令 2.在出现的界面编写cron表达式  3.编写guard_java_extbork.sh脚本 #!/bin/bash source /etc/profil ...

  3. Kubernetes二进制文件下载链接

    这里,我们下载kubernetes的二进制文件在其官网下载即可: 具体链接:https://kubernetes.io/docs/setup/release/notes/

  4. 5分钟搞定!最全Dokploy部署n8n教程

    最近n8n太火了,官方的次数有限,很多人有自己部署的需求.但常规的部署方案总是耗时耗力,拖慢整个开发节奏. 今天我分享一个我自己实践总结的Dokploy部署n8n的超详细教程,帮助你在短短几分钟内完成 ...

  5. .NET Core如何通过认证机制访问Kafka?

    大家好,我是Edison. 最近有一个ASP.NET Core使用认证机制访问Kafka的需求,加之我们又使用了CAP这个开源项目使用的Kafka,于是网上寻找了一番发现对应资料太少,于是调查了一番, ...

  6. Viual Studio 共享组件、工具和SDK的位置不能更改 解决方案

    https://blog.csdn.net/weixin_41923658/article/details/103214742 找到电脑上 VS 的注册表,删除共享组件.工具和 SDK 的注册表:   ...

  7. C# 泛型对象转Get请求参数

    /// <summary>        /// 对象转Get请求参数        /// </summary>        /// <returns>< ...

  8. C#源生成器:让你的代码飞起来的黑科技

    大家好,我是token.今天想和大家聊聊C#源生成器这个神奇的技术. 说起源生成器,可能很多同学会想:又是什么新的轮子?我反射用得好好的,为什么要学这个?别急,看完这篇文章,你就会发现源生成器简直是性 ...

  9. C++求最长的一条食物链的长度。DFS深度优先算法

    题目描述 如图所示为某生态系统的食物网示意图,据图回答第一小题. 1. 数一数,在这个食物网中最长的食物链包含的物种数是 ( ) ...... 现在给你 n 个物种和 m 条能量流动关系,求其中的食物 ...

  10. 从崩溃到稳定:前端开发者必学的 Node.js 守护进程实战指南

    本文原创首发于公众号[我做开发那些年]与网站[乔文小屋],现同步转载至本平台,点击阅读原文 声明:如需转载本文至其他平台,请注明文章来源及公众号信息,感谢您对原创内容的尊重与支持! 说到守护进程,绝大 ...