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 ...
随机推荐
- JavaScript和JQuery中的事件\委托链\事件冒泡\事件捕获,兼容所有浏览器
有做过北大青鸟培训讲师经验的我,如今在一家公司做技术部经理的职位,发现有很多程序员的基本功相当糟糕,在组织企业内部培训时讲解了一些案例,总结了一些经典代码,希望对自己和有需要的人提供一些帮助吧: Ja ...
- 为什么百度首页的HTML源代码最后一行要多一行?浪费空间呀!
为什么百度首页的HTML源代码最后一行要多一行?浪费空间呀!
- introduction to python for statistics,analysis笔记2
一.行列式连接concatenate函数,axis=0是垂直拼接,axis=1是水平拼接 x=np.array([[],[,]]); y=np.array([[],[,]]); z=np.concat ...
- CentOS防火墙开启、关闭与开放指定端口
系统为centos 5.5,部署好Tomcat之后却发现输入114.80.*.*:8080(即ip:8080)却无法显示Tomcat默认的首页.由于以前部署在Win Server的VPS上,Linux ...
- php获取某年某月的天数
function days_in_month($month, $year) { // calculate number of days in a month return $month == 2 ? ...
- 【Android】自己定义ListView的Adapter报空指针异常解决方法
刚刚使用ViewHolder的方法拉取ListView的数据,可是总会报异常. 细致查看代码.都正确. 后来打开adapter类,发现getView的返回值为null. 即return null. 将 ...
- angular学习笔记(一)-入门案例
入门实例: 一个购物车产品清单,可以自行改变数量,总价自动计算的小例子: 代码如下: <!DOCTYPE html> <html ng-app> <head> &l ...
- postgresql MVCC详解
postgresql MVCC详解 1.postgresql隐藏列 1)tableoid 表对象唯一标识符 2)xmin 插入操作的事务标识符 3)xmax 删除操作的事务标识符 4)cmin 插入操 ...
- vim学习日志(5):vim下wimrc的配置,解决中文乱码问题
解决linux下vim乱码的情况:(修改vimrc的内容) 全局的情况下:即所有用户都能用这个配置 文件地址:/etc/vimrc 在文件中添加: ,ucs-bom,gb18030,gbk,gb231 ...
- 李洪强iOS开发之-sql数据库的使用
一,创建工程 二: 导入头文件 三:导入 四: 数据库增删改查 //因为是结构体类型,所以用assign //1.创建数据库(保存路径) @property(nonatomic,assign)sqli ...