1. 程式人生 > >CF 689D A區間最大值等於B區間最小值的區間個數統計

CF 689D A區間最大值等於B區間最小值的區間個數統計

turn 區間最小值 tdi bit r+ tab urn 題意 ont

  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區間最小值的區間個數統計