Description

一个数组,要求先对前n个数字排序(以方便后续操作);又要求对前n+i个数字排序;又要求对前n+j … 前n+k个数字排序(i、j、k的大小远小于n,且i、j、k间没有大小关系)。总之就是对一个不定的范围内数据要进行频繁的按大小顺序调用,但是这个范围边界变化不大,很多数据重叠,这样每次都对此次区间内数据排序,频繁排序的话很费时间。

例如一个数组{1,3,6,5,2,4,1,9,0},一共9个数字,下标0~8。要求:

每次取一个区间,计算区间内(最大值−最小值)2+(次大值−次小值)2+(次次大值−次次小值)2+...的值。很容易想到对区间排个序,即可方便获得最大、次大值等。

对1~5排序:{2,3,4,5,6}

对1~6排序:{1,2,3,4,5,6}

对2~5排序:{2,4,5,6}

可以看出2、5、6始终在范围内,但每次都要针对所选区间重新排序,很麻烦。

既然大部分数据一直出现在范围内,现在就希望能够一次排序,应对所有情况。

Key

继续使用上述的例子:Array={1,3,6,5,2,4,1,9,0}

开个新数组作其索引:Index={0,1,2,3,4,5,6,7,8}

令索引数组按照Array的大小关系排序,得Index={8,0,6,4,1,5,3,2,7}

对于区间[1, 5]:从左向右找出第一个在[1, 5]的下标即为最小值:8不符合、0不符合、6不符合,4符合,那么最小值就是Array[4]=2,次大值就是Array[1]=3 …

即每次只需检测排序后当前位的数字的下标是否在该区间内即可。

Sample

题目:https://hihocoder.com/problemset/problem/1384

一道贪心的题,期间需要对下标i到j、i到j+k之间的数字分别排序。是别人家的代码(他的原文链接,虽然我也不知道他是不是转别人的),就是在这学到的技巧。注意观察judge函数与judge2函数的差异,judge2函数即实现了上述排序思想。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long int ll;
ll m,n,k;
ll a[500050];
ll b[500050];
int cnt=0;
inline bool cmp(int x,int y)
{
return a[x]<a[y];
}
bool judge(int l,int r)
{
int pos=0;
while(l+pos<=r)b[pos]=a[l+pos],pos++;
sort(b,b+pos);
pos--;
int mid=(pos-1)/2;
ll res=0;
for(int i=0; i<=mid&&i<m; i++)
{
res+=(b[i]-b[pos-i])*(b[i]-b[pos-i]);
if(res>k)
return false;
}
return res<=k;
}
void init(int l,int r)
{
cnt=0;
for(int i=l; i<=r; i++)b[cnt++]=i;
sort(b,b+cnt,cmp);
}
bool judge2(int r)
{
int i,j,kk;
ll res=0;
for(i=0,j=cnt-1,kk=m; kk; i++,j--,kk--)
{
while(i<j&&b[i]>r)i++;
while(i<j&&b[j]>r)j--;
if(i>=j)break;
res+=(a[b[i]]-a[b[j]])*(a[b[i]]-a[b[j]]);
if(res>k)break;
}
return res<=k;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=0; i<n; i++)
scanf("%lld",&a[i]);
int ans=0;
int l=0;
while(l<n)
{
int kk=1;
while(kk+l<n&&judge(l,l+kk))
kk*=2;
int first=l+kk/2,last=l+kk-1<n?l+kk-1:n-1;
init(l,last);
int mid;
int pos=l;
while(first<=last)
{
if(judge2(mid=(first+last)/2))
{
first=mid+1;
pos=mid;
}
else
last=mid-1;
}
l=pos+1;
ans++;
}
cout<<ans<<endl;
}
return 0;
}

[笔记]ACM笔记 - 排序小技巧的更多相关文章

  1. ACM 刷题小技巧【转】

    转载自URl-team ACM做题过程中的一些小技巧. 1.一般用C语言节约空间,要用C++库函数或STL时才用C++; cout.cin和printf.scanf最好不要混用. 大数据输入输出时最好 ...

  2. HTML+CSS笔记 CSS中级 一些小技巧

    水平居中 行内元素的水平居中 </a></li> <li><a href="#">2</a></li> &l ...

  3. [笔记]ACM笔记 - 利用FFT求卷积(求多项式乘法)

    卷积 给定向量:, 向量和: 数量积(内积.点积): 卷积:,其中 例如: 卷积的最典型的应用就是多项式乘法(多项式乘法就是求卷积).以下就用多项式乘法来描述.举例卷积与DFT. 关于多项式 对于多项 ...

  4. [笔记]ACM笔记 - 组合数

    一.高中数学公式复习 , (好吧这个没学过但是既然看到了就一并抄过来了) 二.快速求组合数取模C(n, m)%p 当n和p大小不同时方法有不同. 1. n很小,p随意,p不需要为素数 1) 原理 使用 ...

  5. [笔记]ACM笔记 - 自用模板

    长期更新. 快速幂 lld pow_mod(lld a, lld b, const int &pr) { lld ans = 1; while (b) { if (b & 1) ans ...

  6. HTML+CSS笔记 CSS笔记集合

    HTML+CSS笔记 表格,超链接,图片,表单 涉及内容:表格,超链接,图片,表单 HTML+CSS笔记 CSS入门 涉及内容:简介,优势,语法说明,代码注释,CSS样式位置,不同样式优先级,选择器, ...

  7. lua学习笔记11:lua中的小技巧

    lua中的小技巧,即基础lua语言本身的特种,进行一个些简化的操作 一. 巧用or x = x or v 等价于: if not x then x = v end 假设x为nil或false,就给他赋 ...

  8. ACM 做题过程中的一些小技巧。

    ACM做题过程中的一些小技巧. 1.一般用C语言节约空间,要用C++库函数或STL时才用C++; cout.cin和printf.scanf最好不要混用. 2.有时候int型不够用,可以用long l ...

  9. 《Algorithm算法》笔记:元素排序(2)——希尔排序

    <Algorithm算法>笔记:元素排序(2)——希尔排序 Algorithm算法笔记元素排序2希尔排序 希尔排序思想 为什么是插入排序 h的确定方法 希尔排序的特点 代码 有关排序的介绍 ...

随机推荐

  1. 读书笔记 effective c++ Item 38 通过组合(composition)为 “has-a”或者“is-implemented-in-terms-of”建模

    1. 什么是组合(composition)? 组合(composition)是一种类型之间的关系,这种关系当一种类型的对象包含另外一种类型的对象时就会产生.举个例子: class Address { ...

  2. elasticsearch使用river同步mysql数据

    ====== mysql的river介绍======      - 什么是river?river代表es的一个数据源,也是其它存储方式(如:数据库)同步数据到es的一个方法.它是以插件方式存在的一个e ...

  3. Spark处理日志文件常见操作

    spark有自己的集群计算技术,扩展了hadoop mr模型用于高效计算,包括交互式查询和 流计算.主要的特性就是内存的集群计算提升计算速度.在实际运用过程中也当然少不了对一些数据集的操作.下面将通过 ...

  4. 在centOS7.2安装配置zabbix监控

    zabbix由两部分组成,zabbix-server与可选的zabbix-agent.zabbix-server可以通过SNMP,ZABBIX-AGENT,PING,端口监视等方法提供对远程服务器/网 ...

  5. 容易忽略的z-index失效问题

    前些天写一个模仿虎牙网站幻灯片的插件,期间遇到我一直都没注意到的问题,就是z-idnex会失效的问题. 我是将幻灯片的左右按设置为float浮动的,然后在调试点击的时候发现无论怎么调高z-index都 ...

  6. C++学习笔记之模板篇

    title: C++学习笔记之模板篇 tags: c++,c,模板,vector,friend,static,运算符重载,标准模板 --- 一.模板 不管是函数模板还是类模板,在未初始化前都是不占用内 ...

  7. char , unsigned char 和 signed char 区别

    ANSI C 提供了3种字符类型,分别是char.signed char.unsigned char.char相当于signed char或者unsigned char,但是这取决于编译器!这三种字符 ...

  8. spring项目log4j使用入门

    log4j是Java开发中经常使用的一个日志框架,功能强大,配置灵活,基本上可以满足项目开发中对日志功能的大部分需求.我前后经历了四五个项目,采用的日志框架都是log4j,这也反应了log4j受欢迎的 ...

  9. C#变量、常量、枚举、预处理器指令知多少

    一.变量 C#共有其中变量类型有:静态变量.实类变量.数组元素.数值参数.引用参数.输出参数和局部变量 先定义一个简单的类来说明,如下: public class VariableDefine { p ...

  10. 回车键搜索 - Enter搜索

    今天写了个 搜索  想来发表发表 <!DOCTYPE html><html lang="en"><head> <meta charset= ...