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;
}

随机推荐

  1. WPF如何给window加阴影效果

    <Style x:Key="WindowStyle1" TargetType="{x:Type Window}"> <Setter Prope ...

  2. Linux信号量(3)-内核信号量

    概念 Linux内核的信号量在概念和原理上和用户态的System V的IPC机制信号量是相同的,不过他绝不可能在内核之外使用,因此他和System V的IPC机制信号量毫不相干. 如果有一个任务想要获 ...

  3. fofa开放免费教育账号类比专业账号!

    用户须知 1.免责声明:本教程作者及相关参与人员对于任何直接或间接使用本教程内容而导致的任何形式的损失或损害,包括但不限于数据丢失.系统损坏.个人隐私泄露或经济损失等,不承担任何责任.所有使用本教程内 ...

  4. MySQL 亿级数据平滑迁移实战

    作者:来自 vivo 互联网服务器团队- Li Gang 本文介绍了一次 MySQL 数据迁移的流程,通过方案选型.业务改造.双写迁移最终实现了亿级数据的迁移. 一.背景 预约业务是 vivo 游戏中 ...

  5. 2024-08-28:用go语言,给定一个从1开始、长度为n的整数数组nums,定义一个函数greaterCount(arr, val)可以返回数组arr中大于val的元素数量。 按照以下规则进行n次

    2024-08-28:用go语言,给定一个从1开始.长度为n的整数数组nums,定义一个函数greaterCount(arr, val)可以返回数组arr中大于val的元素数量. 按照以下规则进行n次 ...

  6. ES7学习笔记(四)字段类型(mapping)

    在上一节中,我们创建了索引,在创建索引的时候,我们指定了mapping属性,mapping属性中规定索引中有哪些字段,字段的类型是什么.在mapping中,我们可以定义如下内容: 类型为String的 ...

  7. 登录Harbor仓库报错:Error response from daemon: Get

    登录Harbor仓库报错: docker login -u admin -p Harbor12345 20.20.10.162 WARNING! Using --password via the CL ...

  8. Qt表格入门

    摘要     表格作为数据展示的界面,会在很多场景下使用.Qt为我们提供了使用简单方便和扩展性强的表格视图,这里做一个简单的入门整理.     个人能力有限,有错误欢迎留言指正,如果你有更好的方法,也 ...

  9. docker安装及基本的镜像拉取

    docker 使用存储库安装 卸载它们以及相关的依赖项. yum remove docker \ docker-client \ docker-client-latest \ docker-commo ...

  10. T2回家(home)题解

    T2回家(home) 现在啥也不是了,虽然会了逆元,但是对期望概率题还是一窍不通,赛时相当于只推出了 \(n=1\) 的情况,结果运用到所有情况,理所应当只有20分. 题目描述 小Z是个路痴.有一天小 ...