AtCoder Beginner Contest 408 E-F 题解
E. Minimum OR Path
题意
给你一个 \(N\) 个点 \(M\) 条边的无自环的无向图,第 \(i\) 条边连接 \(u_i\) 和 \(v_i\),权值为 \(w_i\)。
在所有从 \(1\) 到 \(n\) 的简单路径(不经过同一点两次的路径)中,找到边权或和的最小值。
思路
贪心。把最终答案转换成二进制数看,接下来所说的高位、低位都指二进制位:
可以发现,越高位的贡献越大,而且二进制数 \(100000>011111\),即,只要高位是 \(0\),不管低位怎么增加都还是比原来小;
所以,要使答案最小,首先要使高位尽可能小。
那就可以从高位往低位贪心,假设一开始的答案的 \(31\) 位每一位都是 \(1\)。从第 \(31\) 位开始,假设这一位是 \(0\),并把这个图的边全部删除(认为这个图上只有点,无边,后续逐渐加边),然后将所有的满足 \([ 其边权的(当前位)和(之前已经确定不是 1的位)不是 1]\) 的边全部加入这个图,检测这个图是否连通。
若连通,说明这一位可以为 \(0\),且这一位为 \(0\) 时的对答案的贡献一定比为 \(1\) 时的小,所以将答案的这一位设为 \(0\);
否则,说明这一位只能为 \(1\),那么答案的这一位还是 \(1\),保留原值。
接下来说一下如何判断图是否联通:使用并查集(\(\text{DSU}\))。对于每一位,处理之前先把 \(fa_i\) 初始化为 \(i\),然后,对于每条满足要求(上面已经说过了)的边 \((u,v)\),将 \(fa_{find(v)}=fa_{find(u)}\)。
时间复杂度为 \(O(N+M)\times\log N)\)。
C++ 代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=200005;
int n,m;
int fa[maxn];
struct Node{
int u,v,w;
}e[maxn];
int find(int x){
if(fa[x]==x) return fa[x];
return fa[x]=find(fa[x]);
}
signed main(){
cin>>n>>m;
int one=0,zero=0;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
e[i]={u,v,w};
}
for(int a=30;a>=0;a--){
for(int i=1;i<=n;i++){
fa[i]=i;
}
for(int i=1;i<=m;i++){
if(e[i].w&(zero|(1<<a))) continue;
int u=e[i].u,v=e[i].v;
if(u>v) swap(u,v);
if(find(u)==find(v)) continue;
fa[find(v)]=fa[find(u)];
}
if(find(n)==find(1)){
zero|=(1<<a);
}else{
one|=(1<<a);
}
}
cout<<one<<endl;
return 0;
}
F. Athletic
题意
有 \(N\) 个架子,第 \(i\) 个高度为 \(H_i\),\(H\) 为长度为 \(N\) 的排列。一开始,你可以选择站在任意一个架子上,当你在架子 \(i\) 上时,你可以移动到满足以下条件的任意一个架子 \(j\) 上:
- \(H_i-H_j \ge D\) 且 \(1\le |i-j|\le R\) (\(D\) 和 \(R\) 已经给定)。
求出你的最大移动次数。
思路
考虑动态规划。设 \(f_i\) 表示到高度为 \(i\) 的那个架子移动的最大次数,\(pos_i\) 表示 \(i\) 在 \(H\) 中出现的位置。
则朴素的转移为 \(f_i=\max_{[1\le j\le N ]且[pos_i-R\le pos_j\le pos_i+R]且[j-i\ge D]}f_j+1\)。
显然这个复杂度是 \(O(N^2)\) 的,所以我们要想出一个 \(O(\log n)\) 或 \(O(1)\) 查询区间最大值的方法。
考虑线段树维护区间最大值,对于每个高度 \(i\),将 \(f_{i+D}\) 的值加入线段树(若 \(i+D>N\) 就不加),然后区间查询 \([pos_i-R,pos_i+R]\) 的最大值为 \(p\),则 \(f_i=p+1\)。最终最大的 \(f_i\) 值即为答案。
时间复杂度 \(O(N\log N)\)。
C++ 代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=2e9;
const int maxn=500005;
struct SEGMENT_TREE{
int mx[maxn<<2];
void init(){memset(mx,-1,sizeof(mx));}
void update(int x,int pos,int val,int l,int r){
if(l==r) return void(mx[x]=val);
int mid=l+r>>1;
if(pos<=mid) update(x<<1,pos,val,l,mid);
else update(x<<1|1,pos,val,mid+1,r);
mx[x]=max(mx[x<<1],mx[x<<1|1]);
}
int query(int x,int L,int R,int l,int r){
if(L<=l&&r<=R) return mx[x];
int mid=l+r>>1,ans=-inf;
if(L<=mid) ans=max(ans,query(x<<1,L,R,l,mid));
if(R>mid) ans=max(ans,query(x<<1|1,L,R,mid+1,r));
return ans;
}
}TR;
int h[maxn],f[maxn];
int pos[maxn];
signed main(){
int n,D,R;
cin>>n>>D>>R;
TR.init();
for(int i=1;i<=n;i++){
cin>>h[i];
pos[h[i]]=i;
}
for(int i=n;i>=1;i--){
if(i+D<=n) TR.update(1,pos[i+D],f[i+D],1,n);
f[i]=TR.query(1,max(1ll,pos[i]-R),min(n,pos[i]+R),1,n)+1;
}
int ans=0;
for(int i=1;i<=n;i++){
ans=max(ans,f[i]);
}
cout<<ans<<endl;
return 0;
}
AtCoder Beginner Contest 408 E-F 题解的更多相关文章
- AtCoder Beginner Contest 238 A - F 题解
AtCoder Beginner Contest 238 \(A - F\) 题解 A - Exponential or Quadratic 题意 判断 \(2^n > n^2\)是否成立? S ...
- AtCoder Beginner Contest 221 A~E题解
目录 A - Seismic magnitude scales B - typo C - Select Mul D - Online games E - LEQ 发挥比较好的一场,就来搓篇题解. F ...
- AtCoder Beginner Contest 131 Task F. Must Be Rectangular
Score: 600 points Approach 固定横坐标 $x$,考虑横坐标为 $x$ 的竖直线上最多可以有几个点. Observations 若最初两条竖直线 $x_1$.$x_2$ 上都有 ...
- 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 ...
- 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 ...
随机推荐
- JMeter 线程重复读取在跑数据的解决方法
场景: 需要模拟 100 个账号,100个并发,循环登录登出系统:由此引起了一个问题,如果线程10比线程1提前结束,那么线程10会按 cvs 顺序读取,就有可以读取到目前还在其他线程里面的一个账号: ...
- linux安装python centos
下载安装包 可以到官网 ftp 地址,复制指定 python 版本源码安装包下载链接 https://www.python.org/ftp/python/ 或者到官网 downloads, 复制指定 ...
- 视觉SLAM第四讲李群与李代数习题
视觉SLAM第四讲李群与李代数习题 一.验证\(SO(3).SE(3).SIM(3)\)关于乘法成群 首先引入一下群的定义. 群 (Group) 是一种集合加上一种运算的代数结构.我们把集合记作 \( ...
- cURL 工具库基本使用
cURL(Client URL)是一个功能强大的工具和库,用于与各种网络协议进行交互,cURL常用的一些参数和示例代码: -X, --request :指定HTTP请求方法(GET.POST.PUT等 ...
- 抽象类和接口的对比、及各自的使用场景--java进阶day02
1.区别 2.各自的使用场景 1.抽象类的使用场景 如图,有三个类,其中存在共性,我们就会写一个父类并抽取出共性的东西,但有的方法难免会描述不清,所以我们就将其写为了抽象方法,抽象方法又得存在于抽象类 ...
- for循环的注意事项
1.注意事项! 实操 可以看见上图,当{}里的循环走完后,i还存在,但是a消失了,因此{}里的变量会在每一次循环结束后释放 . 这也是为什么之前我们打印a会出错的原因:a早就已经从内存中释放了,还怎么 ...
- Visual Studio 2017 导出 ASP.NET Core 项目模版项目文件为空
问题重现 VS 2017 针对 ASP.NET Core 导出模版功能有问题 解决办法 visual-studio-2017-templates-and-the-missing-content 目前官 ...
- leetcode每日一题:最少翻转操作数
题目 2612. 最少翻转操作数 给你一个整数 n 和一个在范围 [0, n - 1] 以内的整数 p ,它们表示一个长度为 n 且下标从 0 开始的数组 arr ,数组中除了下标为 p 处是 1 以 ...
- springboot集成docker实现自动化构建镜像说明
springboot集成docker实现自动化构建镜像说明 文档说明 该文档仅包括通过配置springboot.docker.jenkins.git.appollo等实现持续构建,持续发布的功能,不包 ...
- 详细介绍Java的SPI机制
一.什么是SPI机制 SPI(Service Provider Interface),是JDK内置的一种 服务提供发现机制,可以用来启用框架扩展和替换组件,主要是被框架的开发人员使用,比如java.s ...