A - Thermometer

按题意判断并输出即可。

时间复杂度\(O(1)\)。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
double x;
signed main(){
cin>>x;
if(x>=38) cout<<"1\n";
else if(x>=37.5) cout<<"2\n";
else cout<<"3\n";
return 0;
}

B - Ticket Gate Log

令\(c\)表示当前位应为哪个字符,初始为i

从左到右遍历每个字符\(s_i\):

  • 如果\(s_i=c\),就将\(c\)取反;
  • 如果\(s_i\ne c\),就累加\(1\)的贡献。

时间复杂度\(O(n)\)。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
string s;
int ans=0;
char c='i';
signed main(){
cin>>s;
for(char i:s){
if(i==c) c=(c=='i'?'o':'i');
else ans++;
}
cout<<ans+(c=='o')<<"\n";
return 0;
}

C - Variety Split Easy

分别令\(lef_i,rig_i\)表示\(A\)长度为\(i\)的前缀和后缀有多少不同的元素。

则答案为\(\max\limits_{i=1}^{n-1} (lef_i+rig_i)\)。

\(lef,rig\)可以在遍历过程中,用桶计算出来。

可以用数组、unordered_set等数据结构作为桶。

时间复杂度为\(O(n)\)。

点击查看代码
#include<bits/stdc++.h>
#define N 300010
using namespace std;
int n,a[N],ans;
unordered_set<int> se;
int lef[N],rig[N];
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
se.insert(a[i]);
lef[i]=se.size();
}
se.clear();
for(int i=n;i>=1;i--) se.insert(a[i]),rig[i]=se.size();
for(int i=1;i<n;i++) ans=max(ans,lef[i]+rig[i+1]);
cout<<ans<<"\n";
return 0;
}

D - Cubes

因式分解可得:\(x^3-y^3=(x-y)(x^2+xy+y^2)\)。

如果我们可以枚举\(d=x-y\),即\(x=d+y\)……

那我们仅需判断\(N=d[(d+y)^2+(d+y)y+y^2]\),即\(3y^2+3dy+(d^2-\frac{N}{d})=0\)是否有正整数解即可。

由于\(x^2+xy+y^2\ge (x-y)^3\),所以\((x-y)^3\le N\),即\(d\le \sqrt[3]{N}\),因此枚举\(d\)的时间复杂度是\(O(\sqrt[3]{N})\)。

接下来考虑对于每个\(d\),如何判断是否有整数解。

  • 可以用二次方程求根公式完成判定,时间复杂度为\(O(1)\),不过实现起来比较繁琐;
  • 考虑到二次项、一次项系数都为正,所以上式在\(x>0\)时是单增的,所以我们也可以使用二分法

    显然仅需在\([1,\sqrt N]\)内二分即可,时间复杂度为\(O(\log\sqrt N)\),实现起来较为简单。

代码使用二分法,总时间复杂度为\(O(\sqrt[3]{N}\log\sqrt N)\)。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int solve(int a,int b,int c){
int l=1,r=1e9;
while(l<r){
int x=(l+r+1)>>1;
if(a*x*x+b*x+c<=0) l=x;
else r=x-1;
}
return a*l*l+b*l+c==0?l:-1;
}
signed main(){
cin>>n;
for(int d=1;d*d*d<=n;d++){
if(n%d) continue;
int y=solve(3,3*d,d*d-n/d);
if(~y) cout<<d+y<<" "<<y<<"\n",exit(0);
}
cout<<"-1\n";
return 0;
}

E - Path Decomposition of a Tree

定义\(siz_u\)为子树\(u\)的大小,\(fa_u\)为\(u\)的父节点,\(ch_u\)为\(u\)的子节点个数。

定义\(t_u=siz_u\bmod k\)。不难发现,其含义就是“为了将子树\(u\)的节点全部用链覆盖,子树\(u\)外最少要用多少个节点”。

比如\(t_u=0\)就表示子树\(u\)的答案为Yes

选定一个节点\(R\)作为根节点,开始遍历每棵树,对于节点\(u\),输出No的情况显然只有下面\(3\)种:

  • \((\sum\limits_{fa_v=u} [t_v\ne 0])>2\)。
  • \((\sum\limits_{fa_v=u} t_v)+1>k\)。
  • \(ch_u=2\)且\((\sum\limits_{fa_v=u} t_v)\ne k\)。

特别地,对于根节点\(R\),如果\(t_R\ne 0\),输出No

不过根据数据范围,节点数一定是\(k\)的倍数,所以一定有\(t_R=0\),就不用讨论了。

时间复杂度\(O(nk)\)。

点击查看代码
#include<bits/stdc++.h>
#define NN 200010
#define int long long
using namespace std;
int n,k;
vector<int> G[NN];
void add(int u,int v){G[u].emplace_back(v);}
int dfs(int u,int fa){
int cnt=0,sum=1;
for(int i:G[u]){
if(i==fa) continue;
int t=dfs(i,u);
if(!t) continue;
if(cnt==2) cout<<"No\n",exit(0);
sum+=t,cnt++;
}
if(sum>k||(cnt==2&&sum!=k)) cout<<"No\n",exit(0);
return sum%k;
}
signed main(){
cin>>n>>k;
for(int i=1,u,v;i<n*k;i++){
cin>>u>>v;
add(u,v),add(v,u);
}
dfs(1,0);
cout<<"Yes\n";
return 0;
}

F - Variety Split Hard

如果第\(2\)个区间的右端点已经确定为\(i\),我们仅需考虑第\(1\)个区间的右端点如何选择,即\(a_{1\sim i}\)分成\(2\)个区间的答案。

先考虑用另一种方法解决C——统计每一个位置对答案的贡献。

  • 如果\(a_i\)在\(a_{1\sim i}\)中是唯一的,那么第\(1\)个区间的右端点设在任何位置都会产生\(1\)的贡献。
  • 如果\(a_i\)在\(a_{1\sim i}\)中不是唯一的,定义\([1,i)\)中最大的\(p\)使得\(a_p=a_i\),那么:
    • 如果第\(1\)个区间的右端点\(\in [p,i)\),则对该位置产生\(1\)的贡献。
    • 否则对该位置产生\(0\)的贡献。

用线段树维护每个位置的总贡献,这些总贡献的最大值即为答案。

之所以用这种方法来考虑C题,是因为它可以很轻易地被推广。仅需顺序遍历\(i\in [1,n]\),在统计完前\(i\)个的贡献之后,就用\([1,i]\)每个位置总贡献的最大值,再加上“\(a_{(i+1)\sim n}\)中互不相同的值的个数”,更新答案即可。

按上面的步骤,会把区间为空的情况一并统计进来。不过想一想就能发现,存在空区间的答案一定不会优于每个区间都非空的答案。所以正确性是可以保证的。

时间复杂度\(O(n\log n)\)。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define N 300010
#define lc (x<<1)
#define rc (x<<1|1)
using namespace std;
int n,a[N],suf[N],last[N],ans;
bitset<N> vis;
struct Node{int tag,maxx;}s[N<<2];
void build(int x,int l,int r){
if(l==r) return;
int mid=(l+r)>>1;
build(lc,l,mid),build(rc,mid+1,r);
}
void pushdown(int x){
s[lc].maxx+=s[x].tag,s[lc].tag+=s[x].tag;
s[rc].maxx+=s[x].tag,s[rc].tag+=s[x].tag;
s[x].tag=0;
}
void chr(int x,int a,int b,int l,int r,int v){
if(a<=l&&r<=b) return s[x].maxx+=v,s[x].tag+=v,void();
pushdown(x);
int mid=(l+r)>>1;
if(a<=mid) chr(lc,a,b,l,mid,v);
if(b>mid) chr(rc,a,b,mid+1,r,v);
s[x].maxx=max(s[lc].maxx,s[rc].maxx);
}
int query(int x,int a,int b,int l,int r){
if(a<=l&&r<=b) return s[x].maxx;
pushdown(x);
int mid=(l+r)>>1,ans=0;
if(a<=mid) ans=max(ans,query(lc,a,b,l,mid));
if(b>mid) ans=max(ans,query(rc,a,b,mid+1,r));
return ans;
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=n;i>=1;i--) suf[i]=suf[i+1]+!vis[a[i]],vis[a[i]]=1;
build(1,1,n);
for(int i=1;i<=n;i++){
if(last[a[i]]) chr(1,last[a[i]],i-1,1,n,1);
else chr(1,1,n,1,n,1);
last[a[i]]=i;
ans=max(ans,suf[i+1]+query(1,1,i,1,n));
}
cout<<ans<<"\n";
return 0;
}

这道题还有加强版:https://codeforces.com/problemset/problem/833/B,如果有空会写题解。

[题解]AtCoder Beginner Contest 397(ABC397) 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. Leangoo助力医药行业项目降本增效

    医药行业痛点诸多,制药研发周期长.生物技术创新协同难.医疗器械研发生产衔接不畅.医疗保健服务流程繁琐.Leangoo 可化解困境,促各领域信息共享.流程优化.协同增效,提升效率与质量,推动医药行业整体 ...

  2. ImportError: lxml.html.clean module is now a separate project lxml_html_clean

    导包报错 from lxml_html_clean import Cleaner 解决报错:"ImportError: lxml.html.clean module is now a sep ...

  3. .tar.gz 软件压缩包打包 AppImage 指南

    要想打包 AppImage 分3步走 生成 AppDir 拷贝资源及依赖文件 生成 AppImage 准备工作 下载打包工具 linuxdeploy appimagetool 下载/解压 好要打包的程 ...

  4. CAN304 W4

    CAN304 W4 The public-key revolution 对称加密 (symmetric cryptograph) 带来了一系列安全问题: 如何安全地共享密钥?(The key-dist ...

  5. Vue2和Vue3的差异化(通俗易懂)

    一.相同点 响应式系统(Reactive) 两者都采用 "模板 + 响应式" 的开发模式,视图自动随着状态变化而更新. 都支持双向绑定(v-model).条件渲染(v-if/v-s ...

  6. 在centos7等旧版linux上用国内源下载源码编译安装gcc并配置环境变量

    原文永久链接:https://forum.piwind.com/d/23-zai-centos7deng-jiu-ban-linuxshang-yong-guo-nei-yuan-xia-zai-yu ...

  7. SQL Server中使用临时表进行数据备份与恢复

    在日常的数据库管理中,我们经常需要对数据进行备份和恢复操作.SQL Server提供了多种工具和命令来帮助我们完成这些任务.本文将介绍一种简单的方法,即使用临时表来备份特定记录,清空表,然后将数据恢复 ...

  8. 在C#中使用 System.Threading.Timer 实现定时任务

    在C#中使用 System.Threading.Timer 实现定时任务 (qq.com) 前言 在编写应用程序过程中,高效的任务调度都是必不可少的,无论是在实现后台服务.自动化任务或者定期数据处理. ...

  9. C# datagridView 表格渲染变色 ( 动态改变表格值) 绘制时改变表格值

    private void DGV_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)        {           ...

  10. batocera添加游戏

    进入batocera系统之后,会发现就只有几个不懂什么东西的模拟器,或者FC和其它,好象没有发现可以用NS或者其它的模拟器,在此说明 一下: 整个系统至少支持73个以上模拟器,主界面没有仅因为你没有放 ...