Problem Link

简要题意

翻译很清楚。

思路

提供一种简单直接的思路。

可以发现最多会操作 \(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 题解的更多相关文章

  1. CF977C Less or Equal 题解

    Content 给定一个 \(n\) 个数的数列 \(a_1,a_2,a_3,...,a_n\) 和一个数 \(k\),试找出这样的一个数 \(x\),使得数列中有 \(k\) 个数小于等于 \(x\ ...

  2. Codehorses T-shirts (map+遍历)

    Codehorses has just hosted the second Codehorses Cup. This year, the same as the previous one, organ ...

  3. CF1656E Equal Tree Sums 题解

    题目链接 思路分析 自认为是一道很好的构造题,但是我并不会做. 看了题解后有一些理解,在这里再梳理一遍巧妙的思路. 我们先来看这样的一张图: 我们发现当去掉叶子节点的父亲时,剩下树的价值和等于叶子节点 ...

  4. PAT甲题题解-1053. Path of Equal Weight (30)-dfs

    由于最后输出的路径排序是降序输出,相当于dfs的时候应该先遍历w最大的子节点. 链式前向星的遍历是从最后add的子节点开始,最后添加的应该是w最大的子节点, 因此建树的时候先对child按w从小到大排 ...

  5. PAT甲题题解-1060. Are They Equal (25)-字符串处理(科学计数法)

    又是一道字符串处理的题目... 题意:给出两个浮点数,询问它们保留n位小数的科学计数法(0.xxx*10^x)是否相等.根据是和否输出相应答案. 思路:先分别将两个浮点数转换成相应的科学计数法的格式1 ...

  6. 题解 CF1206B 【Make Product Equal One】

    感谢 @一个低调的人 (UID=48417) 题目: CodeForces链接 Luogu链接 思路: 这是一个一眼题 我们不妨把所有的数都看做是\(1\)(取相应的花费,如:\(6\) 的花费就是\ ...

  7. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  8. LeetCode Minimum Moves to Equal Array Elements II

    原题链接在这里:https://leetcode.com/problems/minimum-moves-to-equal-array-elements-ii/ 题目: Given a non-empt ...

  9. LeetCode Minimum Moves to Equal Array Elements

    原题链接在这里:https://leetcode.com/problems/minimum-moves-to-equal-array-elements/ 题目: Given a non-empty i ...

  10. 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 ...

随机推荐

  1. 实操开源版全栈测试工具RunnerGo安装(三)MacOS安装

    以Sonoma 14.1.2系统为例 视频教程:https://www.bilibili.com/video/BV1fG411e7h2/?spm_id_from=333.999.0.0 1.下载并安装 ...

  2. 【Android 逆向】看雪题目:找出flag 如果输入正确则屏幕上的 hello会变成success

    1. apk 安装到手机,只有一个输入框,随便输入点什么,提示error 2. apk拖入到jadx中 public class MainActivity extends AppCompatActiv ...

  3. 项目实战:Qt监测操作系统物理网卡通断v1.1.0(支持windows、linux、国产麒麟系统)

    需求   使用Qt软件开发一个检测网卡的功能.  兼容windows.linux,国产麒麟系统(同为linux) Demo   windows上运行:       国产麒麟操作上运行:       功 ...

  4. 【Azure 云服务】Cloud Service Worker Role Workerrole突然停机,查看Events发现 Defrag Error (0x8900002D)

    问题描述 Cloud Service Worker Role Workerrole突然停机,查看Events,发现是错误源为 Defrag. 错误消息: The volume Windows was ...

  5. MAUI发布APK初体验

    目的 很早就有想编写安卓程序玩玩的念头了,所以这次学习将MAUI程序生成apk包来玩. 本文apk下载地址:https://azrng.lanzouv.com/iBQRe0eeg8wf ,内容很简单, ...

  6. 感慨 vscode 支持win7最后一个版本 1.70.3 于2022年7月发布

    为什么 家里电脑一直是win7,也懒的升级,nodejs也不能用最新的,没想到vscode也停产了 https://code.visualstudio.com/updates/v1_70 后记 别用u ...

  7. 2023中山市第三届香山杯网络安全大赛初赛wp

    序 被带飞了 PWN move 先往变量 sskd 写入 0x20 字节,往第二个输入点输入 0x12345678 即可进入到第三个输入点,存在 0x8 字节的溢出.思路是在第一个输入点布置 rop ...

  8. Leetcode 1161 最大层内元素和

    一.题目 给你一个二叉树的根节点 root.设根节点位于二叉树的第1层,而根节点的子节点位于第2层,依此类推. 请返回层内元素之和 最大 的那几层(可能只有一层)的层号,并返回其中 最小 的那个. 示 ...

  9. python 音频通道分离的源码实现

    一 前记 作为一个音频工程师,仅仅依靠鼠标点击,没有一些自己的小工具的话,肯定是不合格的了. 最近用到了一个音频通道分离的功能,这里就用python敲击了一下,这里做个备忘吧,给有需求的小伙伴抛砖引玉 ...

  10. Python | Flask 解决跨域问题

    Python | Flask 解决跨域问题 系列文章目录 目录 系列文章目录 前言 使用步骤 1. 引入库 2. 配置 1. 使用 CORS函数 配置全局路由 2. 使用 @cross_origin ...