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) 利用线段树进行区间转移

数学函数区间的最小值与最大值怎么算

CF817D Imbalanced Array

CF817D Imbalanced Array