HDU 5289 Assignment(多校2015 RMQ 单调(双端)队列)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289
ability of any two staff is less than k, and their numbers are continuous. Tom want to know the number of groups like this.
than k. The second line contains n integers:a[1],a[2],…,a[n](0<=a[i]<=10^9),indicate the i-th staff’s ability.
2
4 2
3 1 2 4
10 5
0 3 4 5 2 1 6 7 8 9
5
28HintFirst Sample, the satisfied groups include:[1,1]、[2,2]、[3,3]、[4,4] 、[2,3]
题意:
给出一个整数序列,求有多少个区间满足区间里的最大元素与最小元素的差不超过k”。
PS:
1:能够先用Rmq处理出区间的最值,再枚举区间。当然一味的枚举肯定没有以下两种方法快!
2:用单调(双端)队列维护区间最值
3:枚举左端点,二分右端点,用ST算法求区间最值
代码一例如以下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
const int MAXN = 100117; int num[MAXN]; int F_Min[MAXN][30],F_Max[MAXN][30]; void Init(int n)
{
for(int i = 1; i <= n; i++)
{
F_Min[i][0] = F_Max[i][0] = num[i];
} for(int i = 1; (1<<i) <= n; i++) //按区间长度递增顺序递推
{
for(int j = 1; j+(1<<i)-1 <= n; j++) //区间起点
{
F_Max[j][i] = max(F_Max[j][i-1],F_Max[j+(1<<(i-1))][i-1]);
F_Min[j][i] = min(F_Min[j][i-1],F_Min[j+(1<<(i-1))][i-1]);
}
}
} int Query_max(int l,int r)
{
int k = (int)(log(double(r-l+1))/log((double)2));
return max(F_Max[l][k], F_Max[r-(1<<k)+1][k]);
} int Query_min(int l,int r)
{
int k = (int)(log(double(r-l+1))/log((double)2));
return min(F_Min[l][k], F_Min[r-(1<<k)+1][k]);
}
int solve(int l, int r)
{
return Query_max(l,r)-Query_min(l,r);
}
int main()
{
int t;
int n, k;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
for(int i = 1; i <= n; i++)
{
scanf("%d",&num[i]);
}
Init(n);
__int64 ans = 0;
int pos = 1;
for(int i = 1; i <= n; i++)
{
while(solve(pos, i) >= k && pos < i)
{
pos++;
}
ans+=i-pos+1;
}
printf("%I64d\n",ans);
}
return 0;
}
代码二例如以下:http://www.bubuko.com/infodetail-987302.html
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std ;
#define LL __int64
deque <LL> deq1 , deq2 ;
//单调队列,deq1最大值,deq2最小值
LL a[100010] ;
int main()
{
int t , n , i , j ;
LL k , ans ;
scanf("%d", &t) ;
while( t-- )
{
scanf("%d %I64d", &n, &k) ;
for(i = 0 ; i < n ; i++)
scanf("%I64d", &a[i]) ;
if(k == 0)
{
printf("0\n") ;
continue ;
}
while( !deq1.empty() ) deq1.pop_back() ;
while( !deq2.empty() ) deq2.pop_back() ;
for(i = 0 , j = 0 , ans = 0; i < n ; i++) //i在前,j在后
{
while( !deq1.empty() && deq1.back() < a[i] ) deq1.pop_back() ;
deq1.push_back(a[i]) ;
while( !deq2.empty() && deq2.back() > a[i] ) deq2.pop_back() ;
deq2.push_back(a[i]) ;
while( !deq1.empty() && !deq2.empty() && deq1.front() - deq2.front() >= k )
{
ans += (i-j) ;
//printf("%d %d,%I64d %I64d\n", i , j, deq1.front() , deq2.front() ) ;
if( deq1.front() == a[j] ) deq1.pop_front() ;
if( deq2.front() == a[j] ) deq2.pop_front() ;
j++ ;
}
}
while( j < n )
{
ans += (i-j) ;
j++ ;
}
printf("%I64d\n", ans) ;
}
return 0 ;
}
代码三例如以下:http://www.bubuko.com/infodetail-987919.html
#include<cstdio>
#include<cstring>
#include<cmath>
#define LL long long
#define Max(a,b) ((a)>(b)? (a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std; const int N=200007;
int minn[N][20];//2^18=262144 2^20=1048576
int maxx[N][20]; //----------------------查询O(1)-------------
int queryMin(int l,int r)
{
int k=floor(log2((double)(r-l+1)));//2^k <= (r - l + 1),floor()向下取整函数
return Min(minn[l][k],minn[r-(1<<k)+1][k]);
} int queryMax(int l,int r)
{
int k=floor(log2((double)(r-l+1)));
return Max(maxx[l][k],maxx[r-(1<<k)+1][k]);
}
//------------------------------------------------- int calc(int l,int r)
{
int k=log2((double)(r-l+1));
int MAX=Max(maxx[l][k],maxx[r-(1<<k)+1][k]);
int MIN=Min(minn[l][k],minn[r-(1<<k)+1][k]);
return MAX-MIN;
} int main()
{
int T;
int n,k,i,j,p;
LL ans;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
for(i=1; i<=n; ++i)
{
scanf("%d",&j);
minn[i][0]=maxx[i][0]=j;
}
//------------------------------------------预处理O(nlogn)---------------
for(j=1; (1<<j)<=n; ++j)//1<<j==2^j,枚举区间长度1,2,4,8。16。,。。,
for(i=1; i+(1<<j)-1<=n; ++i)//i+(1<<j)-1表示区间右边界,枚举区间左边界
{
p=(1<<(j-1));
minn[i][j]=Min(minn[i][j-1],minn[i+p][j-1]);
maxx[i][j]=Max(maxx[i][j-1],maxx[i+p][j-1]);
}
//----------------------------------------------------------------------- //---------------------------枚举左端点,二分右端点--------------------------- int l,r,mid;
ans=0;
//左端点固定为i,右端点用l,r,mid去确定,最后用l和r中的当中一个,此时l+1==r
for(i=1; i<=n; ++i)
{
l=i,r=n;
while(l+1<r)
{
mid=(l+r)>>1;//(l+r)/2==(l+r)>>1
if(calc(i,mid)<k)
{
l=mid;
}
else
{
r=mid-1;//自己去演示算法流程就知道r能够赋值mid-1
}
}
if(calc(i,r)<k)
{
ans=ans+(LL)(r-i+1);
}
else
{
ans=ans+(LL)(l-i+1);
}
}
//---------------------------------------------------------------------------
printf("%lld\n",ans);
}
return 0;
}
HDU 5289 Assignment(多校2015 RMQ 单调(双端)队列)的更多相关文章
- Vijos1834 NOI2005 瑰丽华尔兹 动态规划 单调双端队列优化
设dp[t][x][y]表示处理完前t个时间段,钢琴停留在(x,y)处,最多可以走多少个格子 转移时只需逆着当前倾斜的方向统计len个格子(len为时间区间的长度,len=t-s+1),如果遇到障碍就 ...
- HDU 6319 Ascending Rating (单调双端队列)
题意:给定一个序列a[1..n],对于每个长度为m的连续子区间,求出区间的最大值和从左往右扫描该区间最大值的变化次数. 分析:先O(n)处理出整个序列的值.求出每个长度为m的连续区间中的最大值可以用单 ...
- HDU - 5289 Assignment (RMQ+二分)(单调队列)
题目链接: Assignment 题意: 给出一个数列,问其中存在多少连续子序列,使得子序列的最大值-最小值<k. 题解: RMQ先处理出每个区间的最大值和最小值(复杂度为:n×logn),相 ...
- HDU 5289 Assignment [优先队列 贪心]
HDU 5289 - Assignment http://acm.hdu.edu.cn/showproblem.php?pid=5289 Tom owns a company and he is th ...
- 双端队列(单调队列)poj2823 区间最小值(RMQ也可以)
Sliding Window Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 41844 Accepted: 12384 ...
- STL-Deque(双端队列)与单调队列的实现
前言: STl是个好东西,虽然他在不开O2的条件下会跑的很慢,但他着实会让你的代码可读性大大提高,令你的代码看起来既简单又整洁. 双端队列: 顾名思义,双端队列是有两个头的,一个队首指针,一个队尾指针 ...
- 22.1.23Manacher算法、双端队列、单调栈
22.1.23Manacher算法.双端队列.单调栈 1.Manacher算法 1)用途: Manacher算法用于解决类似求某个字符串中最长的回文子串.(回文就是正着读和倒着读一样的结构). 2)算 ...
- 二分+RMQ/双端队列/尺取法 HDOJ 5289 Assignment
题目传送门 /* 题意:问有几个区间最大值-最小值 < k 解法1:枚举左端点,二分右端点,用RMQ(或树状数组)求区间最值,O(nlog(n))复杂度 解法2:用单调队列维护最值,O(n)复杂 ...
- HDU 5289 Assignment(二分+RMQ-ST)
Assignment Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total ...
随机推荐
- 【LeetCode】79. Word Search
Word Search Given a 2D board and a word, find if the word exists in the grid. The word can be constr ...
- C#单线程内存占用过大导致无法创建新的对象
https://msdn.microsoft.com/zh-cn/library/8cxs58a6.aspx 按照csdn原文 默认分配的堆栈大小为1mb 可以通过maxstacksize改变默认 ...
- Win8.1设置ftp服务器并设定用户操作权限的详细教程
http://wenku.baidu.com/link?url=VTDLnDa_yfQN9OldjVnYsOBf7UdIj76QjaLDyHP-I0A6iFEfzB8EyBf9uztwm2JDXlFL ...
- Python max() 函数
描述 max() 函数返回给定参数的最大值,参数可以为序列. 语法 以下是 max() 函数的语法: max( x, y, z, .... ) 参数 x -- 数值表达式. y -- 数值表达式. z ...
- 定时器quartz工具类
一.gradle配置 // https://mvnrepository.com/artifact/org.quartz-scheduler/quartz compile group: 'org.qua ...
- tp表单的提交与验证
一.控制器如下 引用use app\index\model\User; //注意模型类名不能和控制器类名相同 public function index(){ return $this->fet ...
- bs-web项目时会经常打断点跟踪信息,可是循环时总是F10、F10的按,那么把所数据打印出来查看会更方便
bs-web项目时会经常打断点跟踪信息,可是循环时总是F10.F10的按,那么把所数据打印出来查看会更方便 一.打断点的方式适合在有错误产生的时候用很好用. 二.可是在分析数据时不直观,得一个一个循环 ...
- xilinx 官方技术资料
http://china.xilinx.com/support/index.html/content/xilinx/zh/supportNav/ip_documentation.html
- 【Android】20.1 音频播放
分类:C#.Android.VS2015: 创建日期:2016-03-11 一.简介 MediaPlayer:适合每次播放一个音频资源或者音频文件的场合. SoundPool:适合同时播放多个音频资源 ...
- 【Android】5.8 滑动条(SeekBar)
分类:C#.Android.VS2015: 创建日期:2016-02-07 一.简介 滑动条也叫拖动条(用户可拖动改变滑动条的值),比如可让用户调节音量大小.调节屏幕亮度.调节歌曲或视频当前播放的位置 ...