CF 689D A区间最大值等于B区间最小值的区间个数统计
Posted leesongt
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF 689D A区间最大值等于B区间最小值的区间个数统计相关的知识,希望对你有一定的参考价值。
1 /* 2 Source :CF689D 3 题意:给出a,b两个长度为n的数组,问有多少个区间满足max(a[l,r])==min(b[l,r]) len(a)<10^5 4 思路:对于一个固定的l,max(a[l,r])是一个单调不减的序列,min(b[l,r])是一个单调不增的序列, 5 于是可以枚举区间的左端点,然后二分判断右端点的范围 6 快速查询区间的最大最小值可以利用ST表实现。 7 时间 :2018-08-14-12.26 8 */ 9 #include <bits/stdc++.h> 10 using namespace std; 11 12 typedef long long LL; 13 const int MAXN=200005; 14 const LL MOD7 = 1e9+7; 15 16 struct Min_STable 17 { 18 // int a[MAXN]; 19 int dp[MAXN][20]; 20 void init(int *a, int n) 21 { 22 for (int i=1;i<=n;++i) dp[i][0]=a[i]; 23 for (int j=1;(1<<j)<=n;++j) 24 { 25 for (int i=1;i+(1<<j)-1<=n;++i) 26 { 27 dp[i][j]=(dp[i][j-1]<dp[i+(1<<(j-1))][j-1]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1]); 28 } 29 } 30 } 31 int query(int x,int y) 32 { 33 if (x>y) swap(x,y); 34 int k=log(y-x+1)/log(2); 35 return (dp[x][k]<dp[y-(1<<k)+1][k]?dp[x][k]:dp[y-(1<<k)+1][k]); 36 } 37 }Min_st; 38 39 struct Max_STable 40 { 41 int dp[MAXN][20]; 42 void init(int *a,int n) 43 { 44 for (int i=1;i<=n;++i) dp[i][0]=a[i]; 45 for (int j=1;(1<<j)<=n;++j) 46 { 47 for (int i=1;i+(1<<j)-1<=n;++i) 48 { 49 dp[i][j]=(dp[i][j-1]>dp[i+(1<<(j-1))][j-1]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1]); 50 } 51 } 52 } 53 int query(int x,int y) 54 { 55 if (x>y) swap(x,y); 56 int k=log(y-x+1)/log(2); 57 return (dp[x][k]>dp[y-(1<<k)+1][k]?dp[x][k]:dp[y-(1<<k)+1][k]); 58 } 59 }Max_st; 60 61 int a[MAXN]; 62 int b[MAXN]; 63 int n; 64 65 void work() 66 { 67 Max_st.init(a,n); 68 Min_st.init(b,n); 69 LL ans=0; 70 for (int i=1;i<=n;++i) 71 { 72 if (a[i]>b[i]) continue; 73 if (Max_st.query(i,n)<Min_st.query(i,n)) continue; 74 int l=i,r=n; 75 int ml; 76 while (l<=r) 77 { 78 ml=(l+r)/2; 79 // printf("l=%d r=%d ml=%d id_A=%d id_B=%d max_A=%d min_b=%d\n",l,r,ml,Max_st.query(a,i,ml),Min_st.query(b,i,ml),a[Max_st.query(a,i,ml)],b[Min_st.query(b,i,ml)]); 80 if (Max_st.query(i,ml)>=Min_st.query(i,ml)) r=ml-1; 81 else l=ml+1; 82 } 83 if (Max_st.query(i,r+1)!=Min_st.query(i,r+1)) continue; 84 int pl = r+1; 85 l=i,r=n; 86 while (l<=r) 87 { 88 ml=(l+r)/2; 89 // printf("2 l=%d r=%d ml=%d\n",l,r,ml); 90 if (Max_st.query(i,ml)<=Min_st.query(i,ml)) l=ml+1; 91 else r=ml-1; 92 } 93 ans+=(LL) (l-pl); 94 } 95 printf("%I64d\n",ans); 96 } 97 98 int main() 99 { 100 #ifndef ONLINE_JUDGE 101 freopen("test.txt","r",stdin); 102 #endif // ONLINE_JUDGE 103 scanf("%d",&n); 104 for (int i=1;i<=n;++i) scanf("%d",&a[i]); 105 for (int i=1;i<=n;++i) scanf("%d",&b[i]); 106 work(); 107 return 0; 108 } 109 110 //in[1]: 111 //6 112 //1 2 3 2 1 4 113 //6 7 1 2 3 2 114 115 //out[1]: 116 //2
以上是关于CF 689D A区间最大值等于B区间最小值的区间个数统计的主要内容,如果未能解决你的问题,请参考以下文章
CF 689D - Friends and Subsequences
CodeForces 689D Friends and Subsequences
CF #535 (Div. 3) E2 Array and Segments (Hard version) 利用线段树进行区间转移