[笔记]ACM笔记 - 排序小技巧
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笔记 - 排序小技巧的更多相关文章
- ACM 刷题小技巧【转】
转载自URl-team ACM做题过程中的一些小技巧. 1.一般用C语言节约空间,要用C++库函数或STL时才用C++; cout.cin和printf.scanf最好不要混用. 大数据输入输出时最好 ...
- HTML+CSS笔记 CSS中级 一些小技巧
水平居中 行内元素的水平居中 </a></li> <li><a href="#">2</a></li> &l ...
- [笔记]ACM笔记 - 利用FFT求卷积(求多项式乘法)
卷积 给定向量:, 向量和: 数量积(内积.点积): 卷积:,其中 例如: 卷积的最典型的应用就是多项式乘法(多项式乘法就是求卷积).以下就用多项式乘法来描述.举例卷积与DFT. 关于多项式 对于多项 ...
- [笔记]ACM笔记 - 组合数
一.高中数学公式复习 , (好吧这个没学过但是既然看到了就一并抄过来了) 二.快速求组合数取模C(n, m)%p 当n和p大小不同时方法有不同. 1. n很小,p随意,p不需要为素数 1) 原理 使用 ...
- [笔记]ACM笔记 - 自用模板
长期更新. 快速幂 lld pow_mod(lld a, lld b, const int &pr) { lld ans = 1; while (b) { if (b & 1) ans ...
- HTML+CSS笔记 CSS笔记集合
HTML+CSS笔记 表格,超链接,图片,表单 涉及内容:表格,超链接,图片,表单 HTML+CSS笔记 CSS入门 涉及内容:简介,优势,语法说明,代码注释,CSS样式位置,不同样式优先级,选择器, ...
- lua学习笔记11:lua中的小技巧
lua中的小技巧,即基础lua语言本身的特种,进行一个些简化的操作 一. 巧用or x = x or v 等价于: if not x then x = v end 假设x为nil或false,就给他赋 ...
- ACM 做题过程中的一些小技巧。
ACM做题过程中的一些小技巧. 1.一般用C语言节约空间,要用C++库函数或STL时才用C++; cout.cin和printf.scanf最好不要混用. 2.有时候int型不够用,可以用long l ...
- 《Algorithm算法》笔记:元素排序(2)——希尔排序
<Algorithm算法>笔记:元素排序(2)——希尔排序 Algorithm算法笔记元素排序2希尔排序 希尔排序思想 为什么是插入排序 h的确定方法 希尔排序的特点 代码 有关排序的介绍 ...
随机推荐
- MySQL 查询重复的数据,以及部分字段去重和完全去重
1.查找表中多余的重复记录(多个字段) select * from vitae a where (a.peopleId,a.seq) in (select peopleId,seq from vit ...
- windows 安装Beautiful Soup(转)
Beautiful Soup是一个Python的一个库,主要为一些短周期项目比如屏幕抓取而设计.有三个特性使得它非常强大: 1.Beautiful Soup提供了一些简单的方法和Python术语,用于 ...
- AP模块发票过账标记为否检查方法
根据发票编号,查找发票 : 发票过账标记,始终为否,创建会计科目提示如下:
- [.NET] 一步步打造一个简单的 MVC 电商网站 - BooksStore(二)
一步步打造一个简单的 MVC 电商网站 - BooksStore(二) 本系列的 GitHub地址:https://github.com/liqingwen2015/Wen.BooksStore 前: ...
- css2.1实现圆角边框
虽然css3的border-radius实现圆角很简单,但是我还是认为css2.1中好多技术还是很值得学习的,我也是后来才知道这就是传说中的滑动门技术.脑洞大开啊 附上demo <!DOCTYP ...
- 【C++】模拟实现auto_ptr
看了<Effctive C++>,里面提到用对象去管理资源,可以有效防止内存泄漏. 结合auto_ptr特性,稍微思考了一下,实现了一个简单的auto_ptr (因为代码量小,就不分文件了 ...
- 重温Javascript(二)
对象 可以想象成散列表,键值对,值可以是数据或函数 创建对象的方式 1.工厂模式 function createPerson(name, age, job){ var o = new Object() ...
- 采用Spring AOP+Log4j记录项目日志
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6567672.html 项目日志记录是项目开发.运营必不可少的内容,有了它可以对系统有整体的把控,出现任何问题 ...
- js动弹特效
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Git与Github的使用学习
摘要 本文讲解下Git的使用,包括使用Git上传项目工程到Github,文末有彩蛋哦. 1.安装Git 使用apt-get安 sudo apt-get update sudo apt-get inst ...