【题目链接】click here~~

【题目大意】:

给出一个数列,问当中存在多少连续子序列,子序列的最大值-最小值<k

【思路】:枚举数列左端点。然后二分枚举右端点,用ST算法求区间最值。(或用单调队列的思路)

代码:

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long LL;
#define Max(a,b) a>b?a:b
#define Min(a,b) a>b? b:a
#define mem(a,b) memset(a,b,sizeof(a))
int arr[N];
int n,k,m,tmp;
int dp_max[N][20],dp_min[N][20];
void rmq_init(){
for(int i=1; i<=n; ++i) dp_max[i][0]=dp_min[i][0]=arr[i];
double limit=log(n)/log(2.0); // 换底公式
for(int j=1; j<=(int)limit; ++j){
for(int i=1; i+(1<<j)-1<=n; ++i){
dp_max[i][j]=Max(dp_max[i][j-1],dp_max[i+(1<<(j-1))][j-1]);
dp_min[i][j]=Min(dp_min[i][j-1],dp_min[i+(1<<(j-1))][j-1]);
}
}
} int rmq_max(int L,int R){ // 查询[L,R]之间的最大值
int k=floor(log2((double)(R-L+1)));
return Max(dp_max[L][k], dp_max[R - (1<<k) + 1][k]);
} int rmq_min(int L, int R){ // 查询[L,R]之间的最小值
int k=floor(log2((double)(R-L+1)));
return Min(dp_min[L][k], dp_min[R - (1<<k) + 1][k]);
} int solve(int L,int R){
int k=floor(log2((double)(R-L+1)));
int maxx=Max(dp_max[L][k],dp_max[R - (1<<k) + 1][k]);
int minn=Min(dp_min[L][k],dp_min[R - (1<<k) + 1][k]);
return maxx-minn;
} inline LL read(){
int c=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
return c*f;
} int main(){
int t;t=read();
while(t--){
n=read();k=read();
for(int i=1; i<=n; ++i){
arr[i]=read();
}
rmq_init();
LL ans=0;
for(int i=1; i<=n; ++i){//枚举左端点,二分右端点,ST求最值
int ll=i,rr=n;
while(ll<=rr){
int mid=(ll+rr)>>1;
if(solve(i,mid)>=k) rr=mid-1;
else ll=mid+1;
}
if(solve(i,rr)<k)ans+=(rr-i+1);
else ans+=(ll-i+1);
}
printf("%I64d\n",ans);
} return 0;
}

单调队列:

【思路】:

O(n)复杂度

用两个单调队列维护最大值,最小值,相当于双指针,初始,第一个第二个指针指向第一个数据,第一个指针按顺序不断向队尾加入数据,当最大值最小值的差大于等于k后,意味着新加入的这个不能作用于当前第二个指针的位置,也就能计算出,以第二个指针位置開始的连续子序列的个数。最后统计就能够了。

代码:

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long LL;
#define Max(a,b) a>b?a:b
#define Min(a,b) a>b?b:a
#define mem(a,b) memset(a,b,sizeof(a))
int arr[N];
int i,j,n,k,m,tmp;
deque <int >deq_max,deq_min;// maxvalue minvalue
inline LL read(){
int c=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
return c*f;
}
int main(){
int t;t=read();
while(t--){
n=read();k=read();
for(int i=0; i<n; ++i){
arr[i]=read();
}
LL ans=0;
while(!deq_max.empty()) deq_max.pop_back();
while(!deq_min.empty()) deq_min.pop_back();
for(i=0,j=0; i<n; ++i){
while(!deq_max.empty()&&deq_max.back()<arr[i]) deq_max.pop_back();deq_max.push_back(arr[i]);
while(!deq_min.empty()&&deq_min.back()>arr[i]) deq_min.pop_back();deq_min.push_back(arr[i]);
while(!deq_max.empty()&&!deq_min.empty()&&deq_max.front()-deq_min.front()>=k){
ans+=(i-j);
if(deq_max.front()==arr[j]) deq_max.pop_front();
if(deq_min.front()==arr[j]) deq_min.pop_front();
j++;
}
}
while(j<n){
ans+=(i-j);
j++;
}
printf("%I64d\n",ans);
} return 0;
}

HDU 5289 Assignment (二分+区间最值)的更多相关文章

  1. HDU 5289 Assignment [优先队列 贪心]

    HDU 5289 - Assignment http://acm.hdu.edu.cn/showproblem.php?pid=5289 Tom owns a company and he is th ...

  2. HDU 5289 Assignment(二分+RMQ-ST)

    Assignment Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total ...

  3. HDU 5289 Assignment(多校2015 RMQ 单调(双端)队列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289 Problem Description Tom owns a company and he is ...

  4. HDU 5875 st+二分区间

    题目大意:给你n个数,q次询问,每次询问区间[l, r],问a[i]%a[i + 1] % a[i + 2]...%a[j](j <= r)的值 思路:st预处理维护,再二分区间,复杂度n*(l ...

  5. ACM学习历程—HDU 5289 Assignment(线段树 || RMQ || 单调队列)

    Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered fro ...

  6. HDU 4768 (二分区间---涨姿势)

    题意:告诉n组A,B,C,按照A + k * C生成等差数列,问这n组数列中哪个数字出现了奇数次以及出现了几次,题目保证最多只会出现一个这种数字. 分析:读完题并没有思路,后来知道是二分区间,枚举是哪 ...

  7. HDU 5289 Assignment (ST算法区间最值+二分)

    题目链接:pid=5289">http://acm.hdu.edu.cn/showproblem.php?pid=5289 题面: Assignment Time Limit: 400 ...

  8. hdu 5289 Assignment(2015多校第一场第2题)RMQ+二分(或者multiset模拟过程)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289 题意:给你n个数和k,求有多少的区间使得区间内部任意两个数的差值小于k,输出符合要求的区间个数 ...

  9. HDU - 5289 Assignment (RMQ+二分)(单调队列)

    题目链接: Assignment  题意: 给出一个数列,问其中存在多少连续子序列,使得子序列的最大值-最小值<k. 题解: RMQ先处理出每个区间的最大值和最小值(复杂度为:n×logn),相 ...

随机推荐

  1. MySql(四)Select条件查询

    select条件查询的格式如下: SELECT 查询列表FROM 表名WHERE 筛选条件:123456根据筛选条件可以分为以下几类: 按照条件按表达式进行筛选 常用条件运算符如下:> .< ...

  2. vue基础---事件处理

    (1)事件监听 v-on 指令监听 DOM 事件,并在触发时运行JS代码 <div class="event_area"> {{message}} <button ...

  3. 有关bash,我希望我能知晓的十件事

    简介 我之前的一篇文章比我预想的更受欢迎,因此我想再写一篇文章来介绍一些不太知名的bash功能 正如之前所言,由于我觉得bash是一种要经常使用(且需理解)的技术,所以我在研究bash时写了一本书.虽 ...

  4. vue-router + axios token登录状态认证

    vue项目中登录状态判断往往基于jwt认证,我们可以采用判断本地是否存在token,及token是否过期或token值错误 1.利用vue-router 钩子函数判断本地是否存在token impor ...

  5. Linux(Centos7)下搭建SVN服务器(新手上路)

    以前都是别人直接给地址在svn上,下载或者上传东西,如今要自己建一个版本库用来存放东西.1.安装svnyum install -y subversion 2.查看svn安装位置还有哪些文件rpm -q ...

  6. Linux之iptables(五、firewall命令及配置)

    firewalld服务 firewalld是CentOS 7.0新推出的管理netfilter的工具 firewalld是配置和监控防火墙规则的系统守护进程.可以实现iptables,ip6table ...

  7. Linux文件/目录,权限相关

    查看权限 命令 # ls -l filename 结果 -rw-r--r-- l root root 27 11-10 14:50 filename 解析: -rw-r--r-- --共10位 第1位 ...

  8. Python3.0科学计算学习之类

    类: Python中的类是一个抽象的概念,甚至比函数还要抽象.可以把它简单的看作是数据以及由存取.操作这些数据的方法所组成的一个集合.类是Python的核心概念,是面向对象编程的基础. 类有如下的优点 ...

  9. Java核心技术 卷一 复习笔记(甲

    1.数据类型包含八种基本类型,其中四种整形(int/short/long/byte),两种浮点类型(float/double), 一种用于表示Unicode编码的字符类型char,一种表示真值的boo ...

  10. HDU 5115 (2014ACM/ICPC亚洲区北京站) D题(Dire Wolf)

    题目传送门 设dp[i][j]为杀掉区间i到j之间的狼需要付出的最小代价,那么dp[i][j]=min{dp[i][k-1]+dp[k+1][j]+a[k]+b[i-1]+b[j+1]} Java代码 ...