HDU 5289 Assignment (二分+区间最值)
来源:互联网 发布:mac如何恢复苹果系统 编辑:程序博客网 时间:2024/06/05 21:04
【题目链接】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 minvalueinline 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;}
0 0
- HDU 5289 Assignment (ST算法区间最值+二分)
- HDU 5289 Assignment (二分+区间最值)
- HDU 5289 Assignment ST + 二分区间
- 5289 Assignment (RMQ+二分区间)
- HDU 5289 Assignment [RMQ区间查询+二分搜索]
- HDU 5289 Assignment (RMQ+二分)
- HDU 5289 Assignment (二分+RMQ)
- HDU 5289 Assignment(RMQ+二分)
- hdu 5289 Assignment 二分+rmq
- HDU 5289 Assignment【ST+二分】
- hdu 5289(二分+RMQ) Assignment
- HDU 5289 Assignment【二分+RMQ】
- 【二分+RMQ】hdu 5289 Assignment
- Hdu-5289 Assignment (二分+RMQ || 单调队列)
- hdu 2853Assignment (二分图的最大权匹配)
- 514D (二分+区间最值)
- hdu 2853 Assignment(最大权值匹配)
- hdoj 5289 Assignment 【RMQ + 二分查找区间最优长度】
- Gradle学习笔记
- eclipse中在写xml等配置文件的时候,引号中的包、路径等文件不提示的解决方法
- [leetcode-229]Majority Element II(c++)
- 【cocos2d-x 3.7 飞机大战】 决战南海I (九) 飘字特效
- Htpp通讯——Java实现
- HDU 5289 Assignment (二分+区间最值)
- 08-排序3. Talent and Virtue (25)
- 自定义BaseAdapter
- CheckBox,ImageView,ListView
- 【九度OJ1373】|【剑指offer32】整数中1出现的次数(从1到n整数中1出现的次数)
- UITextField 弹出键盘的外观(类型)设置
- ARM处理器启动流程
- Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call
- 【cocos2d-x 3.7 飞机大战】 决战南海I (十) 游戏主场景