hihocoder1384/CH0601 Genius ACM[贪心+倍增+归并排序]
关于lyd给的倍增方法,即从当前枚举向后的$2^k$长度($k$从$1$开始),如果可行就将$k$加一以扩大范围,不可行时将范围不断减半直至$0$。
举个例子,假设当下在1,目标答案是13,那么枚举的范围变化情况是$2$,$4$,$8$,$16$(不行,且范围开始缩小),$12$,$14$(不行),$13$,$13$(范围缩小至0)。
并没有看出这样倍增有什么好处。复杂度可证也是$O(logN)$的,但是不是会带个2左右的常数么。。具lyd所说,当目标答案位置较近时会加快效率。
但是这不影响整体复杂度啊。。带着不很理解的态度看了例题才明白这种倍增姿势相较于二分或者从大到小二倍增的优势所在。
题意:数列$N \leqslant 500000$,求划分最少区间使得每段区间任选$M$对数字(不重复选,不够$M$对的时候能选多少选多少)的差的平方之和小于$K$。
首先很容易证明(cai ce)到对于一列数的最大的上述价值就是将最大数减最小数平方加上次大数减次小数平方加上......也就是排序后头尾相配。可以微调法证明任意一种其他策略不会更优。此贪心为关键之一。
然后因为满足要求的一段区间显然越长越好,所以从起点开始拓展,拓展到最远的地方记下来,反复接替拓展,一定是最小区间数。又因为答案随数列增长是有单调性的,所以可以二分检查找到最远的符合要求的右端点。
每次check时候对区间进行排序,加上二分以及区间数的复杂度,最坏$O(N^2log^2N)$。
可以发现,二分时候每次排序都是一个$O(NlogN)$,因为最坏可能答案在比较靠右的位置。这个时候,lyd给出的倍增方案就派上用场了。
lyd书上描述的倍增方法,总是将复杂度限制在$log($答案区间的长度$)$。假若我们采用这种倍增,那么每次枚举的区间最长长度假设为$K$,则找到这样一个区间的复杂度是$O(Klog^2K)$。(倍增一个$logK$,每次排序一个$KlogK$)而不是原来完整的N。
那么,每个区间的复杂度累加起来,不会超过$O(Nlog^2N)$。很容易证。所以通过限制枚举次数在答案对数内,累加起来就比原来少一个log。这就是这种倍增优势。
但是$O(Nlog^2N)$仍然过不了。考虑到每次都要排序,前面已经可行的区间又被拉进来排了一次,显然浪费时间。于是可以只对当前试探的这段区间排序后,和原来已排好序的两个数列归并。归并完求代价,判断是否满足要求。
每次只对新的一小段排序,总体累加起来每次拓展的排序复杂度是$O(KlogK)$的(对于枚举过头了的区间,虽然不断缩小不断重复排序,但由于每次的排序复杂度折半,总体不会超过原来大区间的两倍)。
而$logK$次倍增每次复制需要$O(K)$,所以也是$O(KlogK)$.
最后,总体累加,复杂度$O(NlogN)$。
这题给予我们几个启发:二分和倍增都可用于有单调性的查找,有时候两者没有什么区别,但有时的check函数复杂度和答案位置有关,倍增可以通过限制此条件使得总体复杂度优化掉。
代码写起来的话还是很少的。
WA记录:
- line61智障没考虑边界。
- line49笔误。。
- line59每次初始值。。哎可能是我倍增没有操作好
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define dbg(x) cerr<<#x<<" = "<<x<<endl
#define _dbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl
using namespace std;
typedef long long ll;
template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
namespace io{
const int SIZE = ( << ) + ;
char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - , c, qu[]; int f, qr;
#define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
inline void flush (){fwrite (obuf, , oS - obuf, stdout);oS = obuf;}
inline void putc (char x){*oS ++ = x;if (oS == oT) flush ();}
template <class I>
inline void read(I &x) {for (f = , c = gc(); c < '' || c > ''; c = gc()) if (c == '-') f = -;
for (x = ; c <= '' && c >= ''; c = gc()) x = x * + (c & ); x *= f;}
template <class I>
inline void print (I x){
if (!x) putc (''); if (x < ) putc ('-'), x = -x;while(x) qu[++ qr] = x % + '', x /= ;while (qr) putc (qu[qr--]);}
struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io::read;
using io::putc;
using io::print;
const int N=+;
int a[N],tmp[N],b[N],c[N];//c:临时排序数组 b:已归并好的数组 tmp:临时归并数组
ll k;
int T,n,m,ans; inline void Merge(int L,int R,int r){
int i=L,j=R+;
for(register int k=L;k<=r;++k)
if(b[i]<c[j]&&i<=R||j>r)tmp[k]=b[i++];
else tmp[k]=c[j++];
}
inline ll calc(int L,int R,int r){
if(r==R)return k+;//_dbg(L,R),dbg(r);
for(register int i=R+;i<=r;++i)c[i]=a[i];
sort(c+R+,c+r+);
Merge(L,R,r);
ll ret=;//for(register int i=L;i<=r;++i)printf("%d ",tmp[i]);puts("");
for(register int i=L;i<=L+_min(m,(r-L+>>))-;++i)ret+=(tmp[r-i+L]-tmp[i])*1ll*(tmp[r-i+L]-tmp[i]);
return ret;
} int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
read(T);while(T--){
read(n),read(m),read(k);
for(register int i=;i<=n;++i)read(a[i]);
ans=;int L=,R=,p,r;
while(L<=n){
p=;b[L]=a[L];
while(p){
if(calc(L,R,r=_min(n,R+p))<=k){
for(register int i=L;i<=r;++i)b[i]=tmp[i];
R=r,p<<=;
}
else p>>=;
}
L=R+,R=L,++ans;
}
print(ans);putc('\n');
}
return ;
}
hihocoder1384/CH0601 Genius ACM[贪心+倍增+归并排序]的更多相关文章
- CH0601 Genius ACM【倍增】【归并排序】
0601 Genius ACM 0x00「基本算法」例题 描述 给定一个整数 M,对于任意一个整数集合 S,定义“校验值”如下: 从集合 S 中取出 M 对数(即 2∗M 个数,不能重复使用集合中的数 ...
- $CH0601\ Genius\ ACM$ 倍增优化DP
ACWing Description 给定一个长度为N的数列A以及一个整数T.我们要把A分成若干段,使得每一段的'校验值'都不超过N.求最少需要分成几段. Sol 首先是校验值的求法: 要使得'每对数 ...
- ACM-ICPC Beijing 2016 Genius ACM(倍增+二分)
描述 给定一个整数 M,对于任意一个整数集合 S,定义“校验值”如下: 从集合 S 中取出 M 对数(即 2∗M 个数,不能重复使用集合中的数,如果 S 中的整 数不够 M 对,则取到不能取为止),使 ...
- AcWing:109. 天才ACM(倍增 + 归并排序)
给定一个整数 MM,对于任意一个整数集合 SS,定义“校验值”如下: 从集合 SS 中取出 MM 对数(即 2∗M2∗M 个数,不能重复使用集合中的数,如果 SS 中的整数不够 MM 对,则取到不能取 ...
- hihocoder--1384 -- Genius ACM (倍增 归并)
题目链接 1384 -- Genius ACM 给定一个整数 m,对于任意一个整数集合 S,定义“校验值”如下:从集合 S 中取出 m 对数(即 2*M 个数,不能重复使用集合中的数,如果 S 中的整 ...
- Contest Hunter 0601 Genius ACM
Genius ACM Advanced CPU Manufacturer (ACM) is one of the best CPU manufacturer in the world. Every d ...
- [hihocoder #1384] Genius ACM 解题报告(倍增)
题目链接:http://hihocoder.com/problemset/problem/1384 题目大意: 给定一个整数 M,对于任意一个整数集合 S,定义“校验值”如下: 从集合 S 中取出 M ...
- hihoCoder#1384 : Genius ACM
对于一个固定的区间$[l,r]$,显然只要将里面的数字从小到大排序后将最小的$m$个和最大的$m$个配对即可. 如果固定左端点,那么随着右端点的右移,$SPD$值单调不降,所以尽量把右端点往右移,贪心 ...
- Codeforces 980E The Number Games 贪心 倍增表
原文链接https://www.cnblogs.com/zhouzhendong/p/9074226.html 题目传送门 - Codeforces 980E 题意 $\rm Codeforces$ ...
随机推荐
- win2008系统:iis配置备份和还原简单操作
(2013-09-26 16:33:22) 转载▼ 分类: 开发类 当我们电脑系统有大量的站点和虚拟目录的时候,电脑因为种种原因需要重做系统,那么重装系统后这些站点我们是否只能一个一个的添加,如果 ...
- python二级考试知识点——turtle、random、time、PyInstaller、jieba、wordcloud
turtle库(必考) 1.from turtle import * #导入turtle库中的所有方法 2.turtle.pensize(size) #画笔的大小 3.turtle.pencolor( ...
- AKKA文档2.3(java版)—什么是角色
原文:http://doc.akka.io/docs/akka/2.3.5/general/actors.html译者:Vitas 什么是角色? 前面角色系统一节介绍了一群角色如何形成一个层次结构,并 ...
- Django重写用户模型报错has no attribute 'USERNAME_FIELD'
目录 Django重写用户模型报错has no attribute 'USERNAME_FIELD' 在重写用户模型时报错:AttributeError: type object 'UserProfi ...
- 使用Python基于OpenCV的验证码识别
Blog:https://blog.csdn.net/qq_40962368/article/details/89312429(Verification_Code_Identification) 步骤 ...
- F12 开发人员工具中的控制台错误消息
使用此参考解释显示在 Internet Explorer 11 的控制台 和调试程序中的错误消息. 简介 使用 F12 开发人员工具进行调试时,错误消息(例如 EC7111 或 HTML1114)将显 ...
- Mysql学习(一)之简单介绍
数据库简介 数据库分类 关系型数据库:MySQL.Oracle.SQLServer.Access.db2.fox pro 文件型数据库:sqlite.mongodb 空间型数据库: 数据库分为两端 数 ...
- 关于redis的几件小事(三)redis的数据类型与使用场景
1.string 这是最基本的类型了,就是普通的set和get,做简单的kv缓存. 2.hash 这个是类似map的一种结构,这个一般就是可以将结构化的数据,比如一个对象(前提是这个对象没嵌套其他的对 ...
- 浅析HBase:为高效的可扩展大规模分布式系统而生
什么是HBase Apache HBase是运行在Hadoop集群上的数据库.为了实现更好的可扩展性(scalability),HBase放松了对ACID(数据库的原子性,一致性,隔离性和持久性)的要 ...
- css简单动画(transition属性)
一.对transition属性的认识 1.transition 属性是一个简写属性,可用于设置四个过渡属性:transition-property 过渡效果的 CSS 属性的名称(height ...