Make It Equal 题解
简要题意
翻译很清楚。
思路
提供一种简单直接的思路。
可以发现最多会操作 \(n\) 次。
那么就可以每次直接枚举切的高度 \(h\),检查更改是否超过 \(k\),之后暴力修改这一段,然后重复以上步骤。
但是直接这样做是 \(\mathcal{O}(n^3)\)。
发现需要维护区间和,那么就可以直接使用线段树维护,寻找比 \(h\) 大的数可以使用二分(将原数组排序,在线段树上用单点查询二分),修改操作使用线段树推平,只修改比 \(h\) 大的数并不影响单调性所以可以重复以上操作。
这样复杂度就是 \(\mathcal{O}(n \log^3{n})\),因为需要单点查询所以多了一个 \(\mathcal{O}(\log{n})\)。
然后继续考虑优化。
如图:

发现可以递推出切高度 \(h\) 的贡献开始部分。
记录 \(pos_i\) 为切高度 \(i\) 时贡献开始的位置。
例如上图中,\(pos_1 = 1,pos_2=2,pos_3=4,pos_4=5\)。
切成高度 \(h\) 后,\(pos_i (i \in [1,h-1])\) 并不受影响。
然后复杂度就只有 \(\mathcal{O}(n \log^2{n})\),顺利通过。
code
#include <cstdio>
#include <queue>
#include <cstring>
#include <vector>
#include <algorithm>
#include <ctype.h>
using i64 = long long ;
const int N = 2e5 + 5 ;
char *p1,*p2,buf[1<<20];
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
inline i64 read(){
i64 x=0,fh=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')fh=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*fh;
}
void Write(i64 x){
if(x>9)Write(x/10);
putchar(x%10+'0');
}
inline void write(i64 x){
if(x<0)putchar('-'),x=-x;
Write(x);
}
int n;
i64 k;
i64 a[N],minn = 0x7fffffffff;
struct SegmentTree{
int lazy[N<<2];
i64 sum[N<<2];
void build(int k = 1,int l = 1,int r = n) {
if(l == r) {sum[k] = a[l];return;}
int mid = l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
sum[k] = sum[k<<1] + sum[k<<1|1];
}
void pushdown(int k,int l,int r) {
if(!lazy[k]) return;
int mid = l+r>>1;
sum[k<<1] = (mid-l+1)*lazy[k];
sum[k<<1|1] = (r-mid) * lazy[k];
lazy[k<<1] = lazy[k];
lazy[k<<1|1] = lazy[k];
lazy[k] = 0;
}
i64 QuerySum(int k,int l,int r,int x,int y) {
if(x <= l && r <= y) return sum[k];
pushdown(k,l,r);
int mid = l+r>>1;
i64 val = 0;
if(x <= mid)
val += QuerySum(k<<1,l,mid,x,y);
if(y > mid)
val += QuerySum(k<<1|1,mid+1,r,x,y);
return val;
}
void change(int k,int l,int r,int x,int y,i64 val) {
if(x <= l && r <= y) {
sum[k] = (r-l+1)*val;
lazy[k] = val;
return;
}
pushdown(k,l,r);
int mid = l+r>>1;
if(x <= mid)
change(k<<1,l,mid,x,y,val);
if(y > mid)
change(k<<1|1,mid+1,r,x,y,val);
sum[k] = sum[k<<1] + sum[k<<1|1];
}
}t;//优化1 线段树
int pos[N];
bool check(int mid){
int x = pos[mid];
if(x == n+1) return 1;
return t.QuerySum(1,1,n,x,n) - (i64)mid * (n-x+1) <= k;
}
int main(){
n=read(),k=read();
for(int i = 1; i <= n; i++) {
a[i] = read();
minn = std::min(minn,a[i]);//最后所有数一定是最小的
}
std::sort(a+1,a+n+1);
for(int i = 1; i <= n; i++)
if(pos[a[i]]) pos[a[i]] = std::min(pos[a[i]],i);//注意细节
else pos[a[i]] = i;
for(int i = 200000; i; i--)
if(!pos[i]) pos[i] = pos[i+1]; // 记录切高度i时贡献从哪开始
t.build();
int ans = 0;
while(true) {
if(t.QuerySum(1,1,n,1,n) == minn * n) break;
int l = minn, r = 200000;
int x = -1;
while(l <= r) {
int mid = l+r>>1;
if(check(mid)) r = mid-1,x=mid;
else l = mid+1;
}
if(x == -1) break;
ans++;
t.change(1,1,n,pos[x],n,x);//区间推平操作
}
write(ans);
return 0;
}
Make It Equal 题解的更多相关文章
- CF977C Less or Equal 题解
Content 给定一个 \(n\) 个数的数列 \(a_1,a_2,a_3,...,a_n\) 和一个数 \(k\),试找出这样的一个数 \(x\),使得数列中有 \(k\) 个数小于等于 \(x\ ...
- Codehorses T-shirts (map+遍历)
Codehorses has just hosted the second Codehorses Cup. This year, the same as the previous one, organ ...
- CF1656E Equal Tree Sums 题解
题目链接 思路分析 自认为是一道很好的构造题,但是我并不会做. 看了题解后有一些理解,在这里再梳理一遍巧妙的思路. 我们先来看这样的一张图: 我们发现当去掉叶子节点的父亲时,剩下树的价值和等于叶子节点 ...
- PAT甲题题解-1053. Path of Equal Weight (30)-dfs
由于最后输出的路径排序是降序输出,相当于dfs的时候应该先遍历w最大的子节点. 链式前向星的遍历是从最后add的子节点开始,最后添加的应该是w最大的子节点, 因此建树的时候先对child按w从小到大排 ...
- PAT甲题题解-1060. Are They Equal (25)-字符串处理(科学计数法)
又是一道字符串处理的题目... 题意:给出两个浮点数,询问它们保留n位小数的科学计数法(0.xxx*10^x)是否相等.根据是和否输出相应答案. 思路:先分别将两个浮点数转换成相应的科学计数法的格式1 ...
- 题解 CF1206B 【Make Product Equal One】
感谢 @一个低调的人 (UID=48417) 题目: CodeForces链接 Luogu链接 思路: 这是一个一眼题 我们不妨把所有的数都看做是\(1\)(取相应的花费,如:\(6\) 的花费就是\ ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- LeetCode Minimum Moves to Equal Array Elements II
原题链接在这里:https://leetcode.com/problems/minimum-moves-to-equal-array-elements-ii/ 题目: Given a non-empt ...
- LeetCode Minimum Moves to Equal Array Elements
原题链接在这里:https://leetcode.com/problems/minimum-moves-to-equal-array-elements/ 题目: Given a non-empty i ...
- Leetcode-462 Minimum Moves to Equal Array Elements II
#462. Minimum Moves to Equal Array Elements II Given a non-empty integer array, find the minimum n ...
随机推荐
- 面试官不按套路出牌,上来就让聊一聊Java中的迭代器(Iterator ),夺命连环问,怎么办?
写在开头 某大厂的面试现场,一位目光深邃,头顶稀疏的中年面试官坐在椅子上,这时候的我走了进来. 面试官:"小伙子,学过Java中容器和数据结构了吧?" 我:"嗯,学了&q ...
- win32 - GDI+ 高斯模糊的使用
虽然标题中标有GDI+,但其实真正实施的时候并没有用到. 不过GDI+的相关文档有一些关于高斯模糊的api说明,见下面链接: Blur class (gdipluseffects.h) 使用Bl ...
- [BUUCTF][Web][HCTF 2018]WarmUp 1
这题已经标识为php 代码审计题,那么需要搞到源码才行 打开靶机对应的url,展示的是一张笑脸图片 右键查看网页源代码 <!DOCTYPE html> <html lang=&quo ...
- dataclass装饰器
简介 根据定义dataclass时指"一个带有默认值的可变的namedtuple" 简单来说,就是你定义一个很普通的类,@dataclass装饰器可以 帮你生成__repr__._ ...
- 05、etcd 读请求执行流程
本篇内容主要来源于自己学习的视频,如有侵权,请联系删除,谢谢. 1.etcd读请求概览 etcd是典型的读多写少存储,在我们实际业务场景中,读一般占据2/3以上的请求.一个读 请求从client通过R ...
- 浅入kubernetes(3):namespace、node、pod
目前已经完成三篇关于 kubernetes 的文章: 在 Ubuntu 上安装 K8S教程 浅入kubernetes(1):Kubernetes 入门基础 浅入kubernetes(2):Kubern ...
- 连接微信群、Slack 和 GitHub:社区开放沟通的基础设施搭建
NebulaGraph 社区如何构建工具让 Slack.WeChat 中宝贵的群聊讨论同步到公共领域. 要开放,不要封闭 在开源社区中,开放的一个重要意义是社区内的沟通.讨论应该是透明.包容并且方便所 ...
- 彩虹猫IDA分析记录
目录 彩虹猫分析 概述 无参启动 带/main参数启动 带/watchdog参数启动 MBR引导程序和动画程序 第一段 引导代码 第二段 动画代码 其他函数 扭曲桌面 扰乱鼠标 钩子函数 桌面绘制图标 ...
- MFC动态创建控件并添加消息映射
目录 指定ID 对象指针 建立对象 控件样式 消息映射 按钮单击 组合框选中 指定ID 在类中声明并定义按钮控件的起始ID,以控件的类型和功能对动态控件ID进行分组,每组最好定义一个自己的起始ID方便 ...
- C++学习笔记之编程思想
目录 编程思想 单例(Singleton)模式 观察者(Observer)模式 void*.NULL和nullptr C的类型转换 C++的类型转换 适配器(Adapter)模式 泛型编程的思想 模板 ...