codeforces 361 D - Friends and Subsequences
2016-07-13 10:56
344 查看
原题:
Description
Mike and !Mike are old childhood rivals, they are opposite in everything they do, except programming. Today they have a problem they cannot solve on their own, but together (with you) — who knows?
Every one of them has an integer sequences a and b of length n. Being given a query of the form of pair of integers (l, r), Mike can instantly tell the value of
while !Mike can instantly tell the value of
.
Now suppose a robot (you!) asks them all possible different queries of pairs of integers (l, r)(1 ≤ l ≤ r ≤ n) (so he will make exactly n(n + 1) / 2 queries) and counts how many times their answers coincide, thus for how many pairs
is satisfied.
How many occasions will the robot count?
Input
The first line contains only integer n (1 ≤ n ≤ 200 000).
The second line contains n integer numbers a1, a2, ..., an ( - 109 ≤ ai ≤ 109) — the sequence a.
The third line contains n integer numbers b1, b2, ..., bn ( - 109 ≤ bi ≤ 109) — the sequence b.
Output
Print the only integer number — the number of occasions the robot will count, thus for how many pairs
is satisfied.
Sample Input
Input
Output
Input
Output
Hint
The occasions in the first sample case are:
1.l = 4,r = 4 since max{2} = min{2}.
2.l = 4,r = 5 since max{2, 1} = min{2, 3}.
There are no occasions in the second sample case since Mike will answer 3 to any query pair, but !Mike will always answer 1.
提示: 暴力比对所有区间时间复杂度是(n^2)无法通过。
观察发现,如果固定区间左边界L,右边界R一次递增,a_max【L,R】是不减的,即有序。 同样b_min【L,R】是不增的,有序。
所以就可以先枚举左端点,再用二分法去寻找右端点的合法(符合题意的)区间,这个区间会是一个连续的范围。
二分的时候注意 RMQ_a(L,mid) = RMQ_b(L,mid) 的时候如何处理决定了最终结果是右端点的左边界还是右边界。
求区间最值是使用了RMQ算法。(一个很精妙的算法,我之前的博客里有写。)
代码:
Description
Mike and !Mike are old childhood rivals, they are opposite in everything they do, except programming. Today they have a problem they cannot solve on their own, but together (with you) — who knows?
Every one of them has an integer sequences a and b of length n. Being given a query of the form of pair of integers (l, r), Mike can instantly tell the value of
while !Mike can instantly tell the value of
.
Now suppose a robot (you!) asks them all possible different queries of pairs of integers (l, r)(1 ≤ l ≤ r ≤ n) (so he will make exactly n(n + 1) / 2 queries) and counts how many times their answers coincide, thus for how many pairs
is satisfied.
How many occasions will the robot count?
Input
The first line contains only integer n (1 ≤ n ≤ 200 000).
The second line contains n integer numbers a1, a2, ..., an ( - 109 ≤ ai ≤ 109) — the sequence a.
The third line contains n integer numbers b1, b2, ..., bn ( - 109 ≤ bi ≤ 109) — the sequence b.
Output
Print the only integer number — the number of occasions the robot will count, thus for how many pairs
is satisfied.
Sample Input
Input
6 1 2 3 2 1 4 6 7 1 2 3 2
Output
2
Input
3 3 3 3 1 1 1
Output
0
Hint
The occasions in the first sample case are:
1.l = 4,r = 4 since max{2} = min{2}.
2.l = 4,r = 5 since max{2, 1} = min{2, 3}.
There are no occasions in the second sample case since Mike will answer 3 to any query pair, but !Mike will always answer 1.
提示: 暴力比对所有区间时间复杂度是(n^2)无法通过。
观察发现,如果固定区间左边界L,右边界R一次递增,a_max【L,R】是不减的,即有序。 同样b_min【L,R】是不增的,有序。
所以就可以先枚举左端点,再用二分法去寻找右端点的合法(符合题意的)区间,这个区间会是一个连续的范围。
二分的时候注意 RMQ_a(L,mid) = RMQ_b(L,mid) 的时候如何处理决定了最终结果是右端点的左边界还是右边界。
求区间最值是使用了RMQ算法。(一个很精妙的算法,我之前的博客里有写。)
代码:
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> using namespace std; #define MAX(x,y) (((x)>(y)) ? (x) : (y)) #define MIN(x,y) (((x) < (y)) ? (x) : (y)) #define ABS(x) ((x)>0?(x):-(x)) #define ll long long const int inf = 0x7fffffff; const int maxn=2e5+10; int a[maxn],b[maxn]; int d_a[maxn][23]; int d_b[maxn][23]; void RMQ_init_a(int *A,int n) { for(int i=0; i<n; i++) d_a[i][0]=A[i]; for(int j=1; (1<<j)-1 < n; j++) for(int i=0; i+(1<<j)-1 < n; i++) d_a[i][j]=MAX( d_a[i][j-1], d_a[i + (1<<(j-1))][j-1] ); } int RMQ_a(int L, int R) { int k=0; while( 1<<(k+1) <= R-L+1 ) k++; return MAX( d_a[L][k], d_a[R-(1<<k) + 1][k] ); } void RMQ_init_b(int *A,int n) { for(int i=0; i<n; i++) d_b[i][0]=A[i]; for(int j=1; (1<<j)-1 < n; j++) for(int i=0; i+(1<<j)-1 < n; i++) d_b[i][j]=MIN( d_b[i][j-1], d_b[i + (1<<(j-1))][j-1] ); } int RMQ_b(int L, int R) { int k=0; while( 1<<(k+1) <= R-L+1 ) k++; return MIN( d_b[L][k], d_b[R-(1<<k) + 1][k] ); } int main() { int n; cin>>n; for(int i=0; i<n; i++) scanf("%d",a+i); for(int i=0; i<n; i++) scanf("%d",b+i); RMQ_init_a(a,n); RMQ_init_b(b,n); int left, right; ll ans = 0; for(int L=0; L<n; L++) { int left = inf, right = -inf; //求左边界 int l = L; int r = n-1; while(l <= r) { int mid=(l + r)/2; if(RMQ_a(L,mid) > RMQ_b(L,mid)) //左半部分 r=mid-1; else if(RMQ_a(L,mid) < RMQ_b(L,mid)) //右半部分 l=mid+1; else { left = min(left, mid); r=mid-1; } } // printf("left = %d\n",left); //求右边界 l = L; r = n-1; while(l <= r) { int mid=(l + r)/2; if(RMQ_a(L,mid) > RMQ_b(L,mid)) //左半部分 { r=mid-1; } else if(RMQ_a(L,mid) < RMQ_b(L,mid)) //右半部分 l=mid+1; else { right = max(right, mid); l=mid+1; } } // printf("right = %d\n",right); if(left != inf) ans += right - left + 1; } cout<<ans<<endl; return 0; }
相关文章推荐
- easyui容易被忽略掉的部分
- Request对象中可以获取各种路径信息
- [转]easyui data-options的使用
- [转]EasyUI——常见用法总结
- Vue.js——使用$.ajax和vue-resource实现OAuth的注册、登录、注销和API调用
- 异常org.hibernate.QueryException: could not resolve property的原因 解决办法
- 【JDBC 报错】Connections could not be acquired from the underlying database!
- Unique Word Abbreviation
- Easy-ui dialog弹框拖动超出body后无法关闭
- UITableView没数据时用户提示如何做?
- 今天更新Android studio 2.1.2,Instant Run requires 'Tools | Android | Enable ADB integration' to be enabl
- 第12章:图形用户界面GUI
- Unique Paths
- request、response 中文乱码问题
- UITableView(表示图)
- java Integer.valueOf()方法
- UIGraphicsBeginImageContext系列知识
- 开源视频会议BigBlueButton 0.81二次开发API
- POJ 1904 King's Quest 强连通分量+二分匹配
- EasyUI datagrid : 启用行号、固定列及多级表头后,头部行号位置单元格错位的问题