codeforce 689D 【二分+RMQ】
来源:互联网 发布:cos图片特效软件 编辑:程序博客网 时间:2024/06/04 19:26
题意:
给出长度都为n(1<=n<=2e5)的两数组a[i]与b[i],求有多少组l与r使 。
比如a = {1,2,3,2,1,4},b={6,7,1,2,3,2} 有两组l与r符合条件:1.l=4,r=4,max=min=2;2.l=4,r=5,max=min=2。
题解:
我们可以思考当l固定时,可以通过求解r的范围[left,righ]得到(right-left)组符合条件的l与r,这个r的范围求解可以通过二分来求解, 判断在某个范围[l,r]是否符合条件可以通过RMQ在O(1)时间内处理,具体思路如下:
当r在范围[left,right]中可能存在符合条件的值时判断mid(mid=(left+right)/2)是否符合条件,若在[l,mid]范围,Max>Min则说明符合条件的r在[eftl,mid-1]中,Max<Min则说明符合条件的r在[mid+1,right]中,当Max==Min时符合条件的r最小值在[left,mid-1]符合条件的r的最大值在[mid+1,right]中。
这样就可以在O(2*log(n))求解某个固定值l下符合条件的r的范围,再枚举l就可以得到答案,总的时间复杂度为O(n*2*log(n))
#include<iostream>#include <stdio.h>#include <algorithm>#include <cmath>#include<stdlib.h>#include <string.h>#include<queue>#include<set>#include<map>#include<stack>#include<time.h>using namespace std;#define MAX_N 200005#define inf 0x7fffffff#define LL long long#define ull unsigned long long#define mod 1000000007LL INF=9e18;int a[MAX_N];int b[MAX_N];int minsum[MAX_N][20];int maxsum[MAX_N][20];void init_RMQ(int n){ for(int i=1;i<=n;i++) maxsum[i][0] = a[i], minsum[i][0] = b[i]; int k = log2(1.0*n); for(int j=1;j<=k;j++) { for(int i=1;i<=n;i++) { if(i+(1<<j)-1<=n) { maxsum[i][j] = max(maxsum[i][j-1], maxsum[i+(1<<(j-1))][j-1]); minsum[i][j] = min(minsum[i][j-1], minsum[i+(1<<(j-1))][j-1]); } } }}int getMax(int i,int j){ int k = (int)log2(1.0*(j-i+1)); return max(maxsum[i][k], maxsum[j-(1<<k)+1][k]);}int getMin(int i,int j){ int k = (int)log2(1.0*(j-i+1)); return min(minsum[i][k], minsum[j-(1<<k)+1][k]);}int main(){ int n; cin >> n; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&b[i]); init_RMQ(n); LL ans = 0; //固定left,二分right for(int i=1;i<=n;i++) { //如果a[i]比b[i]则跳过,因为接下来Max只会更大Min只会更小 if(a[i] > b[i]) continue; int low = i; int up = n; int l = 0; int r = 0; while(low <= up) { int mid = (low + up) / 2; int Max = getMax(i, mid); int Min = getMin(i, mid); if(Max > Min) up = mid - 1; else if(Max < Min) low = mid + 1; else//假如mid符合条件则right最小值向low靠拢 l = mid, up = mid - 1; } if(l) {//假如存在符合条件的最小值则搜索最大值 up = n; low = l; while(low <= up) { int mid = (low + up) / 2; int Max = getMax(i, mid); int Min = getMin(i, mid); if(Max > Min) up = mid - 1; else if(Max < Min) low = mid + 1; else//假如mid符合条件则right最大值向up靠拢 r = mid, low = mid + 1; } } //printf("%d %d %d\n",i,l,r); if(l && r) { ans = ans + (LL)(r - l) + 1; } } cout << ans << endl;}
0 0
- codeforce 689D 【二分+RMQ】
- codeforces 689D (二分 RMQ)
- Codeforces 689D RMQ+二分
- Codeforce 327D 二分
- codeforce 689C 【二分】
- Codeforces 689D Friends and Subsequences(二分+RMQ)
- Codeforces 689D Friends and Subsequences(二分+RMQ)
- RMQ+二分 - CF 689D Friends and Subsequences
- Codeforces 689D Friends and Subsequences(RMQ+二分)
- Codeforces 689D Friends and Subsequences (RMQ+二分)
- Codeforces 689D Friends and Subsequences(二分+RMQ)
- codeforce 439D 二分或者三分
- 【codeforce 713D】Animals and Puzzle dp+二维rmq
- Codeforces 620D Lipshitz Sequence RMQ+二分
- HDU 5726-D-GCD- RMQ+二分
- codeforces 731D (DP 二分 二维RMQ)
- codeforce 359D 二分+ 动态规划(sparse table)
- Codeforces 689D Friends and Subsequences【思维+二分+RMQ】套路题
- APP测试基本流程
- 机器学习---决策树CART---opencv源码分析
- Android开发中怎样用多进程、用多进程的好处、多进程的缺陷、解决方法
- python 实现单链表
- 构造器能否被重写?
- codeforce 689D 【二分+RMQ】
- STM32高级开发(13)-Ubuntu下的串口助手minicom
- cocos2dx 3.x 修改NDK_ROOT、ANDROID_SDK_ROOT、ANT_ROOT路径
- poj1384 Piggy-Bank 完全背包
- Java使用Apache的FileUpload组件进行文件上传
- 浮动路由+静态路由快速重路由配置
- TCP/UDP的简单相关基础知识点涉及聊天室的实现
- vue1.0学习总结
- [MongoDB]外部json数据导入MongoDB