[题解]AtCoder Beginner Contest 408(ABC408) A~G
A - Timeout
根据题意,若令\(T[0]=0\),则:
- 答案为
Yes\(\iff\)对于\(i\in [1,n]\),都有\(T[i]-T[i-1]\le S\)。
时间复杂度\(O(n)\)。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,s,last;
signed main(){
cin>>n>>s;
for(int i=1,x;i<=n;i++){
cin>>x;
if(x-last>s) cout<<"No\n",exit(0);
last=x;
}
cout<<"Yes\n";
return 0;
}
B - Compression
先排序,再使用unique函数进行去重即可。时间复杂度\(O(n\log n)\)。
点击查看代码
#include<bits/stdc++.h>
#define N 110
using namespace std;
int n,a[N];
signed main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n);
int len=unique(a,a+1+n)-a-1;
cout<<len<<"\n";
for(int i=1;i<=len;i++) cout<<a[i]<<" ";
return 0;
}
也可以使用set等数据结构来实现。时间复杂度是\(O(n\log n)\)。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n;
set<int> s;
signed main(){
cin>>n;
for(int i=1,x;i<=n;i++) cin>>x,s.insert(x);
cout<<s.size()<<"\n";
for(int i:s) cout<<i<<" ";
return 0;
}
C - Not All Covered
定义桶数组\(b\)。对于\(i\in [1,m]\),将\(b[L_i\sim R_i]\)每个位置\(+1\),需要前缀和优化。
最后答案即为\(\min\limits_{i=1}^n b[i]\)。
时间复杂度\(O(n+m)\)。
点击查看代码
#include<bits/stdc++.h>
#define N 1000010
using namespace std;
int n,m,a[N],ans=INT_MAX;
signed main(){
cin>>n>>m;
for(int i=1,l,r;i<=m;i++) cin>>l>>r,a[l]++,a[r+1]--;
for(int i=1;i<=n;i++){
a[i]+=a[i-1];
ans=min(ans,a[i]);
}
cout<<ans<<"\n";
return 0;
}
D - Flip to Gather
赛时思路
定义\(a[i]\)为\(s[1\sim i]\)中\(1\)的个数。
如果最终将\([l,r]\)区间置为\(1\)(由于区间可以为空,所以规定\(r\ge l-1\)),那么操作次数就是:
即:
$$(a[l-1])+(r-l+1-a[r]+a[l-1])+(a[n]-a[r])$$
整理得:
$$a[n]+(2a[l-1]-(l-1))-(2a[r]-r)$$
令$t[i]=2a[i]-i$,则上式$=$
$$a[n]+t[l-1]-t[r]$$
由于$r\ge l-1$,所以我们可以枚举$r$,对于每个$r$,找$t[0\sim r]$的前缀最小值作为$t[l-1]$。
最终答案即为:
\]
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define N 200010
using namespace std;
int t,n,a[N];
string s;
signed main(){
cin>>t;
while(t--){
cin>>n>>s;
s=' '+s;
for(int i=1;i<=n;i++) a[i]=a[i-1]+s[i]-'0';
int tmp=a[n],ans=LLONG_MAX;
for(int i=1;i<=n;i++) a[i]=2*a[i]-i;
for(int i=0,minn=LLONG_MAX;i<=n;i++){
minn=min(minn,a[i]);
ans=min(ans,minn-a[i]);
}
cout<<ans+tmp<<"\n";
}
return 0;
}
题解思路
本质上差不多。
定义\(a[i]\)为\(s[1\sim i]\)中\(0\)的个数,\(b[i]\)为\(s[1\sim i]\)中\(1\)的个数。
如果最终将\([l,r]\)区间置为\(1\),那操作次数就是:
\]
令\(t[i]=b[i]-a[i]\),整理得:
\]
统计起来就和上面同理了。
E - Minimum OR Path
为了让答案尽可能小,我们尽可能要让答案最高位为\(0\),其次要尽可能让答案次高位为\(0\)……于是考虑贪心。
定义集合\(S=\varnothing\),\(S\)中若存在\(i\),则表示“所经过的边,第\(i\)位必须为\(0\)”。
从最高位开始,依次考虑每一位\(k\):
- 如果在\(S\cup\{k\}\)的限制下,仍然能从\(1\)走到\(n\),则令\(S\leftarrow S\cup\{k\}\)。
- 否则,将答案累加\(2^k\)。
第一条的判定可以使用并查集或者DFS来实现。
时间复杂度分别是\(O((n+m)\alpha(n)\log V)\)和\(O((n+m)\log V)\)。
并查集
#include<bits/stdc++.h>
#define N 200010
#define M 200010
#define int long long
using namespace std;
int n,m,ans,fa[N];
struct edge{int u,v,w;}e[M];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(int u,int v){u=find(u),v=find(v);if(u!=v) fa[u]=v;}
signed main(){
cin>>n>>m;
for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].w;
int s=0;
for(int i=29;~i;i--){
s^=(1<<i);
for(int j=1;j<=n;j++) fa[j]=j;
for(int j=1;j<=m;j++) if(!(e[j].w&s)) merge(e[j].u,e[j].v);
if(find(n)!=find(1)) s^=(1<<i),ans^=(1<<i);
}
cout<<ans<<"\n";
return 0;
}
DFS
#include<bits/stdc++.h>
#define N 200010
#define int long long
using namespace std;
int n,m,ans;
struct edge{int to,w;};
vector<edge> G[N];
bitset<N> vis;
void add(int u,int v,int w){G[u].emplace_back(edge{v,w});}
void dfs(int u,int x){
vis[u]=1;
for(auto i:G[u]) if(!vis[i.to]&&!(i.w&x)) dfs(i.to,x);
}
signed main(){
cin>>n>>m;
for(int i=1,u,v,w;i<=m;i++){
cin>>u>>v>>w;
add(u,v,w),add(v,u,w);
}
int s=0;
for(int i=29;~i;i--){
vis=0,dfs(1,s|(1<<i));
if(vis[n]) s|=(1<<i);
else ans|=(1<<i);
}
cout<<ans<<"\n";
return 0;
}
F - Athletic
下文的\(a\)表示高度数组。
考虑DP。令\(f[i]\)表示首次移动到\(i\)的最大可能移动次数。
那么从高到低遍历每个脚手架\(i\),有转移:
\]
如果没有\(a_j\ge a_i+D\)的限制,直接用线段树来维护区间\(\max\)即可。
现在加上了这条限制,我们仅需在遍历到高度\(i\)时,才将高度为\(i+D\)的\(f\)值加入线段树,加入之前初始值都是\(-1\)。这样就满足了线段树里的脚手架高度都\(\ge i+D\)的条件,并且未加入的脚手架不会产生贡献。
时间复杂度\(O(n\log n)\)。
点击查看代码
#include<bits/stdc++.h>
#define N 500010
#define int long long
#define lc (x<<1)
#define rc (x<<1|1)
using namespace std;
int n,d,r,a[N],pos[N],f[N];
struct SEG{
int maxx[N<<2];
void upd(int x){maxx[x]=max(maxx[lc],maxx[rc]);}
void sep(int x,int a,int v,int l,int r){
if(l==r) return maxx[x]=v,void();
int mid=(l+r)>>1;
if(a<=mid) sep(lc,a,v,l,mid);
else sep(rc,a,v,mid+1,r);
upd(x);
}
int query(int x,int a,int b,int l,int r){
if(a<=l&&r<=b) return maxx[x];
int mid=(l+r)>>1,ans=-1e9;
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;
}
}tr;
signed main(){
memset(tr.maxx,-1,sizeof tr.maxx);
cin>>n>>d>>r;
for(int i=1;i<=n;i++) cin>>a[i],pos[a[i]]=i;
for(int i=n;i;i--){//高度
if(i+d<=n) tr.sep(1,pos[i+d],f[i+d],1,n);
f[i]=1+tr.query(1,max(1ll,pos[i]-r),min(n,pos[i]+r),1,n);
}
cout<<*max_element(f+1,f+1+n)<<"\n";
return 0;
}
G - A/B < p/q < C/D
定义\(f(\frac{A}{B},\frac{C}{D})\)为\((P,Q)\)使得:
- \(\frac{A}{B}<\frac{P}{Q}<\frac{C}{D}\)。
- \(Q\)尽可能小。
考虑如何计算\(f(\frac{A}{B},\frac{C}{D})\)。
如果\(\frac{A}{B}<1\)且\(\frac{C}{D}>1\),答案就是\((1,1)\)。
否则将\(\frac{A}{B}\)和\(\frac{C}{D}\)同时取倒数得到\(\frac{B}{A}\)和\(\frac{D}{C}\),再同时减去\(\lfloor\frac{B}{A}\rfloor\)得到\(\frac{B'}{A}\)和\(\frac{D'}{C}\)。
计算\(f(\frac{B'}{A},\frac{D'}{C})\)得到\((p',q')\),按上面的步骤即可反解出原来的\((p,q)\)。
正确性证明下午写。
时间复杂度与gcd相同,是\(O(T\log V)\)。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,a,b,c,d,p,q;
void gcd(int a,int b,int &p,int &q,int c,int d){
if(a<b&&c>d) p=1,q=1;
else{
gcd(d%c,c,q,p,b-(d/c)*a,a);
q+=(d/c)*p;
}
}
signed main(){
cin>>t;
while(t--){
cin>>a>>b>>c>>d;
gcd(a,b,p,q,c,d);
cout<<q<<"\n";
}
return 0;
}
[题解]AtCoder Beginner Contest 408(ABC408) A~G的更多相关文章
- 题解 AtCoder Beginner Contest 168
小兔的话 欢迎大家在评论区留言哦~ AtCoder Beginner Contest 168 A - ∴ (Therefore) B - ... (Triple Dots) C - : (Colon) ...
- [题解] 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 220部分题(G,H)题解
刚开始的时候被E题卡住了,不过发现是个数学题后就开始使劲推式子,幸运的是推出来了,之后的F题更是树形DP换根的模板吧,就草草的过了,看了一眼G,随便口胡了一下,赶紧打代码,毕竟时间不多了,最后也没打完 ...
- [题解] Atcoder Beginner Contest ABC 265 Ex No-capture Lance Game DP,二维FFT
题目 首先明确先手的棋子是往左走的,将其称为棋子1:后手的棋子是往右走的,将其称为棋子2. 如果有一些行满足1在2右边,也就是面对面,那其实就是一个nim,每一行都是一堆石子,数量是两个棋子之间的空格 ...
- AtCoder Beginner Contest 154 题解
人生第一场 AtCoder,纪念一下 话说年后的 AtCoder 比赛怎么这么少啊(大雾 AtCoder Beginner Contest 154 题解 A - Remaining Balls We ...
- AtCoder Beginner Contest 177 题解
AtCoder Beginner Contest 177 题解 目录 AtCoder Beginner Contest 177 题解 A - Don't be late B - Substring C ...
- KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解
KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解 哦淦我已经菜到被ABC吊打了. A - Century 首先把当前年 ...
- AtCoder Beginner Contest 184 题解
AtCoder Beginner Contest 184 题解 目录 AtCoder Beginner Contest 184 题解 A - Determinant B - Quizzes C - S ...
- AtCoder Beginner Contest 173 题解
AtCoder Beginner Contest 173 题解 目录 AtCoder Beginner Contest 173 题解 A - Payment B - Judge Status Summ ...
- AtCoder Beginner Contest 148 题解
目录 AtCoder Beginner Contest 148 题解 前言 A - Round One 题意 做法 程序 B - Strings with the Same Length 题意 做法 ...
随机推荐
- 「Note」您想来点数据结构吗?
大分块系列 最初分块 \(\color{black}{P4119}\) 考虑数列分块+值域分块 数列分块需要维护: \(nid_{i,j}\) \(fid_i\) \(f_i\) 块 \(i\) 中数 ...
- 袋鼠云:基于Flink构建实时计算平台的总体架构和关键技术点
数栈是云原生-站式数据中台PaaS,我们在github和gitee上有一个有趣的开源项目:FlinkX,FlinkX是一个基于Flink的批流统一的数据同步工具,既可以采集静态的数据,也可以采集实时变 ...
- DTALK直播预约 | 数据资产管理:金融机构数据价值释放的必经之路
当前,数据对金融机构业务和发展的重要性日益凸显,释放数据生产力已经成为金融机构进行全面数字化转型的核心,这就要求金融机构以数据资产为纲不断提升自身数据资产管理能力. 本期DTALK我们邀请到雅拓信息解 ...
- 流批一体开源项目ChunJun技术公开课——ChunJun同步Hive事务表
一键直达直播间 一.直播介绍 上两期渡劫同学为大家分享了ChunJun数据还原的DDL模块,想必大家对这一模块有了比较深入的了解,本期无倦同学将会为大家分享ChunJun同步Hive事务表的相关内容, ...
- tgt源码阅读
读懂一个开源项目源码之前,需要先了解该项目的背景知识.背景知识熟悉了,代码只是具体实现手段而已. 源码地址:https://github.com/fujita/tgt 对于tgt来说,背景知识是块设备 ...
- List集合详解
List集合是有序的,可重复的元素.里面每个元素都有索引,通过索引访问元素. List接口是Colletion的子接口,自然可以用里面的方法.额外的增加了通过索引访问集合元素的方法.如下 packag ...
- 如何识别SQL Server中需要添加索引的查询
引言 在数据库性能优化中,索引是提升查询速度最有效的手段之一.然而,不恰当的索引会降低写操作性能并增加存储开销.作为DBA,我们经常面临这样的挑战:如何精准定位哪些查询真正需要添加索引? 本文将分享几 ...
- C# WinForm 自定义控件绑定属性DataBindings
https://www.cnblogs.com/jizhongfong/p/4384689.html var bind = new Binding("Enabled", Order ...
- Bootstrap fileinput(ssm版)
这是一篇我早起学习java-ssm的记录,这里主要是学习了文件上传 Bootstrap fileinput v1.0 前言bootstrap fileinput是一个很好的文件上传插件.但是官方不出a ...
- websocket拦截器,统一处理参数和返回值json数据
前言 传统的ws,发送前后都需要json序列化和反序列化这对编写代码并不友好.所以我做了个优化 废话不多说,上代码 my-ws.js const ws = new WebSocket("ws ...