ABC372 (D,E)
ABC372 (D,E)
D
一道比较简单的二分查找题目。
观察到每个数能成为 \(j\) 的条件是独立的,因此想到统计每个数能成为它前面哪些数的 \(j\)。
对于每个\(ed\), 二分 \(1 \sim ed-1\) 中最后一个大于 \(h[ed]\) 的数的位置 \(st\), 那么 \(h[ed]\) 可作为 \(st \sim ed-1\) 的 \(j\).
二分的检查方法中需要求区间max, 写个st表或者线段树就做完了(参考代码用的线段树)
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=(r);++i)
#define G(i,r,l) for(int i(r);i>=(l);--i)
using namespace std;
using ll = long long;
const int N = 3e5 + 5;
int h[N], ans[N], mx[N << 2];
int n;
void pushup(int u){
mx[u] = max(mx[u * 2], mx[u * 2 + 1]);
}
void update(int u, int l, int r, int x, int y){
if(l == r) {
mx[u] += y;
return ;
}
int mid = (l + r) >> 1;
if(x<=mid) update(u * 2, l, mid, x, y);
else update(u * 2 + 1, mid + 1, r, x, y);
pushup(u);
}
int query(int u, int l, int r, int x, int y){
if(x <= l && r <= y){
return mx[u];
}
int mid = (l + r) >> 1, ret = 0;
if(x <= mid) ret = query(u * 2, l, mid, x, y);
if(y > mid) ret = max(ret, query(u * 2 + 1, mid + 1, r, x, y));
pushup(u);
return ret;
}
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n;
F(i, 1, n) cin >> h[i], update(1, 1, n, i, h[i]);
F(i, 1, n){
int l = 0, r = i, mid;
while(l + 1 < r){
mid = (l + r) >> 1;
if(query(1, 1, n, mid,i-1) > h[i]) l = mid;
else r = mid;
}
ans[l] ++, ans[i]--;
}
F(i, 1, n) ans[i] += ans[i - 1], cout << ans[i] << ' ';
return 0;
}
E
关键在于要读懂 type2 考察的对象是 \(u\) 所在连通块,想到这个,并查集就呼之欲出了。
而查询第 \(k\) 大的话,由于 \(k\) 不超过10, 所以暴力查是可以接受的。
合并用启发式合并保证复杂度控制在 \(O(n logn)\).
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=(r);++i)
#define G(i,r,l) for(int i(r);i>=(l);--i)
using namespace std;
using ll = long long;
const int N = 3e5 + 5;
int n, q;
int fa[N];
set<int,greater<int>> s[N];
inline int get(int x){
return (fa[x] != x) ? fa[x] = get(fa[x]) : x;
}
void merge(int u, int v){
int fu = get(u), fv = get(v);
if(fu == fv) return ;
if((int)s[fu].size() > (int)s[fv].size()){
fa[fv] = fu;
for(auto x : s[fv]){
s[fu].emplace(x);
}
s[fv].clear();
}
else{
swap(fu, fv);// fu:bigger
fa[fv] = fu;
for(auto x : s[fv]){
s[fu].emplace(x);
}
s[fv].clear();
}
}
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n >> q;
F(i, 1, n) fa[i] = i, s[i].emplace(i);
F(i, 1, q){
int op, u, v;
cin >> op >> u >> v;
if(op == 1){
merge(u, v);
}
else{
u = get(u);
if((int)s[u].size() < v){
cout << "-1\n";
continue;
}
for(auto x : s[u]){
if(--v==0){
cout << x << '\n';
break;
}
}
}
}
return 0;
}
随机推荐
- 神经网络之卷积篇:详解卷积步长(Strided convolutions)
详解卷积步长 卷积中的步幅是另一个构建卷积神经网络的基本操作,让向展示一个例子. 如果想用3×3的过滤器卷积这个7×7的图像,和之前不同的是,把步幅设置成了2.还和之前一样取左上方的3×3区域的元素的 ...
- 实习记录day03:尝试写一个接口
前言:今天突然意识到,实习记录很少有技术性的东西,更多的是自己的心里活动和一些感想,其实这类博客更趋向于日记而非技术记录.也许哪天不再充满兴趣了,这个实习记录也就结束了(想下班了同志们) 实习第三天: ...
- WCF实例管理
实例管理是对WCF使用的一系列技术的总称,通过它可以将客户端的请求绑定到服务实例上,并根据客户端请求的类型以确定服务实例的管理方式.由于应用程序在可扩展,性能,吞吐量,事物与对垒调用等方面存在巨大的差 ...
- 甲方扔给两个存在包名与类名均相同的Jar包,要在工程中同时使用怎么办?
你的项目是否曾遇到过有jar包冲突,而这些冲突的jar包又必须同时存在的情况?一般来说,jar 冲突都是因不同的上层依赖项,自身又依赖了相同 jar 包的不同版本所致,解决办法也都是去除其中一个即可. ...
- installer 命令介绍
installer 命令是 macOS 系统中用于在命令行界面下安装 .pkg 格式的安装包的工具.这个命令特别有用于自动化安装软件或者在没有图形用户界面的情况下进行软件安装,比如在远程管理或者终端会 ...
- PyTorch从入门到放弃之张量模块
目录 张量的数据类型 torch.rand()函数 torch.randn()函数 torch.normal()函数 torch.linspace()函数 torch.manual_seed()函数 ...
- SciPy从入门到放弃
目录 SciPy简介 拟合与优化模块 求最小值 曲线拟合 线性代数模块 统计模块 直方图和概率密度函数 统计检验 SciPy简介 SciPy是一种以NumPy为基础,用于数学.工程及许多其他的科学任务 ...
- OpenTelemetry 实战:gRPC 监控的实现原理
前言 最近在给 opentelemetry-java-instrumentation 提交了一个 PR,是关于给 gRPC 新增四个 metrics: rpc.client.request.size: ...
- C++: 智能指针的自定义删除器 `Custom Deleter` 有什么用?
C++11智能指针std::shared_ptr和std::unique_ptr都支持自定义删除器,本文将介绍自定义删除器的使用场景和使用方法.智能指针模板参数的第二个类型是删除器,一般是一个函数指针 ...
- 开源项目dotnet/eshop 和 dotnet/eshopsupport
dotnet/eshop[1] 和 dotnet/eshopsupport[2] 是两个与 .NET 相关的开源项目,分别用于展示电子商务应用的不同方面. dotnet/eshop: 功能与架构:do ...