1. 程式人生 > >51Nod1962 區間計數

51Nod1962 區間計數

else mes clas pac 區間 print turn sin nlogn

這題與之前那道區間最值的題非常類似,依舊是二分區間,然後統計跨過中間點的區間貢獻。

我們要選出小於等於和小於的,這樣就可以算出相等的區間長了。

復雜度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\n",ans); 46 return 0; 47 }

51Nod1962 區間計數