Hiho1384 倍增+归并排序
题目链接:#1384 : Genius ACM
题意: 给定一段数组,按照原有的顺序,将其划分成几个区间,保证每个区间里 任意取出M对数其差的平方和小于K ,如果取不出M 对就尽量多取。
题解:hihocoder1384 Genius ACM(倍增)
【hihocoder#1384】Genius ACM(倍增+归并)
归并排序(复杂度:O(nlogn))详解参见:
图解排序算法(四)之归并排序 (这个里面的代码是java的)
白话经典算法系列之五 归并排序的实现(讲的真好) (代码挺简单明了)
AC代码:
//hihoCoder 1384 归并+倍增
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define eps 1e-9
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,m
#define rson m+1,r
#define PI acos(-1.0)
const int MAXN=5e5+10;
int n,m,_;
ll a[MAXN],b[MAXN],c[MAXN];//a存储原始数据,b存储当前排好序的序列,c存储最新排好序的序列(临时的) 数组用int会WA
ll k;
bool calc(int l,int mid,int r)//归并排序并计算区间[l...r]内的sum值
{for(int i=mid;i<=r;i++)//原始数组右半段区间的数存到数组b中b[i]=a[i];sort(b+mid,b+r+1);//数组b排序if(l==mid)//排除没有左半段的情况,是else情况的一种补充 (归并排序)for(int i=mid;i<=r;i++)c[i]=b[i];else//两个区间分别为[l...mid-1]和[mid...r]{int i=l,j=mid,t=l;//t为c数组下标while(i<mid&&j<=r){if(b[i]<=b[j])c[t++]=b[i++];elsec[t++]=b[j++];}while(i<mid)c[t++]=b[i++];while(j<=r)c[t++]=b[j++];}ll sum=0;/*int len=r-l+1; //计算SPD值 方法1for(int i=l;i<=min(l+len/2-1,l+m-1);i++)sum+=(c[r-i+l]-c[i])*(c[r-i+l]-c[i]);*/int cnt=0;//记录去分区的次数for(int i=l,j=r;i<j;i++,j--)//计算SPD值 方法2{sum+=(c[j]-c[i])*(c[j]-c[i]);//最大的和最小的之差的平方和最大cnt++;if(cnt==m)break;}if(sum<=k){for(int i=l;i<=r;i++)//满足要求之后将已经排好序的c赋值给bb[i]=c[i];return true;}elsereturn false;
}
int main()
{std::ios::sync_with_stdio(false);cin>>_;while(_--){mem(b,0);mem(c,0);cin>>n>>m>>k;for(int i=1;i<=n;i++)cin>>a[i];b[1]=a[1];//从原始数据的第一个开始往后查找int l=1,r=1,p=1,ans=0;//p记录倍增的步数,即拓展的长度,初始值为1while(r<n){if(p)//拓展长度不为0{if(r+p<=n&&calc(l,r+1,r+p))//有区间加上拓展长度之后不超过序列总长n且sum满足条件{r+=p;//继续往后递增p<<=1;//p倍增if(r==n)break;}elsep>>=1;//p倍减}else//拓展长度为0,即已找到一个最远的右端点,则开始下一段的查找{ans++;//结果值++p=1;//p恢复初始值r++;//右端点+1l=r;//左端点更新b[l]=a[l];//当前b[]的开头为a[l]continue;}}if(r==n)ans++;cout<<ans<<endl;}return 0;
}
Hiho1384 倍增+归并排序相关推荐
- CH - 0601 Genius ACM(倍增+归并排序)
题目链接:点击查看 题目大意: 给定一个正整数M,对于任意一个整数集合S,定义"检验值"如下: 从集合S中取出M对数(即2*M个数,不能重复使用集合中的数,如果S中的整数不够M对, ...
- 2019.7.29 金华正睿集训总结Day2
7.29 上午 分治 普通分治 • 通过将区间分成两个区间,来将问题分成两个子问题 例题: • 求所有区间的最大值之和 根据分治思想,对于每个区间,都递归分成两部分,边界为1 对于每个区间,先考虑固定 ...
- NOIP训练营集训笔记—信息学基础算法(倍增与分治算法
本文摘自清北OI学堂内部笔记,作者潘恺璠,来自柳铁一中曾参加过清北训练营提高组精英班,主要记录的是信息学基础算法.笔记非常详细,特分享给大家! NOIP2019年夏令营正在报名中,6大校区10种班 ...
- 经典排序算法-----归并排序(C语言实现)
算法表述: 归并排序的基本原理是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列.其实通俗来说,对于一个数来说自 ...
- ST算法 - RMQ(区间最值问题)—— 倍增
文章目录 引入倍增: 例题1:区间和 例题2:Genius ACM 应用: ST算法 求解 RMQ(区间最值问题) 模板Code: 练习题: ST算法 维护区间最大公约数 例题:Pair of Num ...
- 对LCA、树上倍增、树链剖分(重链剖分长链剖分)和LCT(Link-Cut Tree)的学习
LCA what is LCA & what can LCA do LCA(Lowest Common Ancestors),即最近公共祖先 在一棵树上,两个节点的深度最浅的公共祖先就是 L ...
- 分治算法的设计思想(二分检索、二分归并排序)
分治策略思想: 将原问题划分或者归结为规模较小的子问题. 递归或迭代求解每一个问题. 将子问题的解综合得到原问题的解. 性质: 子问题与原问题具有相同的性质. 子问题的求解彼此独立. 划分时子问题的规 ...
- LightHouse/归并排序
灯塔(LightHouse) 题目见https://dsa.cs.tsinghua.edu.cn/oj/problem.shtml?id=1144 最近复习DSA,便在看邓老师的mooc,顺便做做配套 ...
- 归并排序(代码注释超详细)
归并排序: (复制粘贴百度百科没什么意思),简单来说,就是对数组进行分组,然后分组进行排序,排序完最后再整合起来排序! 我看了很多博客,都是写的8个数据呀什么的(2^4,分组方便),我就想着,要是10 ...
- HDU - 3078 Network 倍增LCA
倍增lca,把路径上点全部拉出来拍个序输出第k大就过了. 不知道怎么过的,咱也不敢问. #include<stdio.h> #include<string.h> #includ ...
最新文章
- python数据结构推荐书-「算法与数据结构」从入门到进阶吐血整理推荐书单
- 一种抑制undershoot/overshoot锐化算法介绍
- SAP Gigya(SAP Customer Data Cloud)的数据中心
- mongo-express 远程代码执行漏洞(CVE-2019-10758)
- 太平鸟上云 推动中国服饰行业新零售转型
- python dlib人脸检测_使用Python+OpenCV+Dlib实现人脸检测与人脸特征关键点识别
- OAuth2.0认证服务器之客户端相关配置
- IS-IS路由协议(一)
- android 专业ps软件,手机专业ps修图
- matlab逻辑符号怎么打,matlab逻辑符号
- 根因定位论文:Root Cause Analysis of Anomalies of Multitier Services in Public Clouds
- python帝国cms_用python 发 帝国cms 文章
- oc贴材质透明logo有问题,logo贴图有底色,oc贴图怎么不平铺
- 相机光学传递函数MTF
- matlab中P代码即P文件加密与逆向工程探讨
- js屏蔽手机的物理返回键
- GPU 资源消耗原因和解决方案:
- 【工作感悟】路自在前,冷暖自知
- 圣诞节来了,怎能还没有圣诞树呢 快来为心爱的她送上专属的圣诞礼物叭~
- 关于RouterOS 国内DDNS服务