【CodeForces - 689D】Friends and Subsequences(RMQ,二分 或单调队列)
題干:
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.
Examples
Input
6 1 2 3 2 1 4 6 7 1 2 3 2Output
2Input
3 3 3 3 1 1 1Output
0Note
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的數組a1,2,3,…n和b1,2,3,….n, 問你有多少個區間[l,r](1<=l<=r<=n), 使得max{al,al+1,al+2….,ar}和min{bl,bl+1,bl+2….,br}的值相等。
解題報告:
因為max隨著區間的增加,具有單調不減的性質,min同理。所以我們可以枚舉左端點,通過二分來確定右端點的一段合法區間。最后統計答案即可。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define FF first #define SS second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e5 + 5; int n; int a[MAX],b[MAX],Log[MAX]; int A[MAX][33],B[MAX][33]; void ST() {for(int i = 1; i<=n; i++) A[i][0] = a[i],B[i][0] = b[i];for(int j = 1; (1<<j)<=n; j++) {for(int i = 1; i+(1<<j)-1<=n; i++) {A[i][j] = max(A[i][j-1],A[i+(1<<j-1)][j-1]);B[i][j] = min(B[i][j-1],B[i+(1<<j-1)][j-1]);}} } int aMax(int l,int r) {int k = Log[r-l+1];return max(A[l][k],A[r-(1<<k)+1][k]); } int bMin(int l,int r) {int k = Log[r-l+1];return min(B[l][k],B[r-(1<<k)+1][k]); } int ans; int main() {for(int i = 2; i<MAX; i++) Log[i] = Log[i>>1] + 1;cin>>n;for(int i = 1; i<=n; i++) cin>>a[i];for(int i = 1; i<=n; i++) cin>>b[i];ST();for(int i = 1; i<=n; i++) {int l = i,r = n,mid,ans1=-1,ans2=0,Mx,Mn;while(l<=r) {mid = (l+r)>>1;Mx=aMax(i,mid),Mn=bMin(i,mid);if(Mx == Mn) ans1 = mid,l = mid+1;else if(Mx>Mn) r = mid-1;else l = mid+1; }l = i,r = ans1;while(l<=r) {mid = (l+r)>>1;if(aMax(i,mid) == bMin(i,mid)) ans2 = mid,r = mid-1;else l = mid+1;}ans += ans1-ans2+1;}cout << ans << endl;return 0 ; }甚至這題還可以用On的單調隊列來寫:
#include <bits/stdc++.h> using namespace std;int n, a[200001], b[200001]; long long ans; deque<int> mx, mn; int main() {scanf("%d",&n);for(int i = 1; i <= n; i++) scanf("%d", &a[i]);for(int i = 1; i <= n; i++) scanf("%d", &b[i]);for(int i = 1, j = 1; i <= n; i++) {while(!mx.empty() and a[mx.back()] <= a[i]) mx.pop_back();while(!mn.empty() and b[mn.back()] >= b[i]) mn.pop_back();mx.push_back(i);mn.push_back(i);while(j <= i and a[mx.front()] - b[mn.front()] > 0) {j++;while(!mx.empty() and mx.front() < j) mx.pop_front();while(!mn.empty() and mn.front() < j) mn.pop_front();}if(!mx.empty() and !mn.empty() and a[mx.front()] == b[mn.front()]) ans += min(mx.front(), mn.front()) - j + 1;}printf("%lld", ans); }總結:
注意別直接這么寫了:
for(int i = 1; i<=n; i++) {int l = i,r = n,mid,ans1=-1,ans2=0;while(l<=r) {mid = (l+r)>>1;if(aMax(i,mid) == bMin(i,mid)) ans1 = mid,l = mid+1;else r = mid-1; }l = i,r = ans1;while(l<=r) {mid = (l+r)>>1;if(aMax(i,mid) == bMin(i,mid)) ans2 = mid,r = mid-1;else l = mid+1;}ans += ans1-ans2+1;}因為他不一定從i開始都是滿足的,所以你求右端點的右邊界的時候必須要分三種情況討論。但是求左邊界的時候就無所謂了。
不好理解的話可以畫個圖,假設一段區間的RMQ如圖所示:(但是注意這不代表答案只是包含一段區間,因為可能有多段這樣的圖形出現。。。但是用單調隊列還是沒有問題的、注意維護值域的時候的判斷條件)
枚舉到以i為左端點時,我們要求的右端點的左右邊界是l和r,所以二分的時候也要舍棄i~l這一段。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的【CodeForces - 689D】Friends and Subsequences(RMQ,二分 或单调队列)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 假如给你1亿现金,一天后就要归还本金,怎
- 下一篇: 年轻人没家底没背景,如何更快攒到100万