51Nod1962 区间计数

这题与之前那道区间最值的题非常类似,依旧是二分区间,然后统计跨过中间点的区间贡献。

我们要选出小于等于和小于的,这样就可以算出相等的区间长了。

复杂度O(nlogn)

By:大奕哥

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 ll ans;int n;
 5 const int N=350005;
 6 void add(ll x){ans+=x;}
 7 int a[2][N],p[2][3],l[2][N],r[2][N];
 8 void solve(int ll,int rr)
 9 {
10     if(ll==rr){if(a[0][ll]==a[1][ll])add(1);return;}
11     int mid=ll+rr>>1;
12     solve(ll,mid);solve(mid+1,rr);
13     for(int k=0;k<=1;++k)
14     {
15         l[k][mid]=a[k][mid];for(int i=mid-1;i>=ll;--i)l[k][i]=max(l[k][i+1],a[k][i]);
16         r[k][mid]=a[k][mid];for(int i=mid+1;i<=rr;++i)r[k][i]=max(r[k][i-1],a[k][i]);
17     }
18     for(int k=0;k<=1;++k)for(int i=0;i<=3;++i)p[k][i]=mid;
19     for(int i=mid;i>=ll;--i)
20     {
21         for(int k=0;k<=1;++k)
22         {
23             while(p[k][0]<rr&&r[k][p[k][0]+1]<=l[k][i])p[k][0]++;
24             while(p[k][1]<rr&&r[k][p[k][1]+1]<l[k^1][i])p[k][1]++;
25             while(p[k][2]<rr&&r[k][p[k][2]+1]<=l[k^1][i])p[k][2]++;
26         }
27         if(l[0][i]==l[1][i])add(max(0,min(p[0][0],p[1][0])-mid));
28         else if(l[0][i]>l[1][i])add(max(0,min(p[1][2],p[0][0])-p[1][1]));
29         else add(max(0,min(p[0][2],p[1][0])-p[0][1]));
30     }
31     int pos=mid+1;
32     for(int i=mid+1;i<=rr;++i)
33     {
34         while(pos>ll&&max(l[1][pos-1],l[0][pos-1])<max(r[1][i],r[0][i]))--pos;
35         if(r[0][i]==r[1][i])add(max(0,mid-pos+1));
36     }
37 }
38 int main()
39 {
40     scanf("%d",&n);
41     for(int k=0;k<=1;++k)
42     for(int i=1;i<=n;++i)
43     scanf("%d",&a[k][i]);
44     solve(1,n);
45     printf("%lld
",ans);
46     return 0;
47 }
原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8075307.html