codeforces 689D

来源:互联网 发布:昆明关键字优化公司 编辑:程序博客网 时间:2024/05/17 03:49

题意:给出两个序列,计算有多少个区间,第一个序列的最大值等于第二个序列的最小值。

题解:注意到第一个区间的最大值递增,第二个区间的最小值递减。我们可以枚举起点,二分相等位置。


#include<bits/stdc++.h>using namespace std;class RMQ{int n;vector<int> Log2;vector<vector<int> > f;vector<int> a;public:RMQ(int n){this->n=n;Log2 = vector<int>(n+1);Log2[1]=0;for(int i=1;i<=n;i++){Log2[i]=Log2[i-1];if(1<<(Log2[i]+1)==i){Log2[i]++;}}f = vector<vector<int> >(n,vector<int>(Log2[n]+1));}RMQ(){}void init(const vector<int> &a){this->a=a;for(int j=0;j<=Log2[n];j++){for(int i=0;i+(1<<j)-1<n;i++){if(j==0){f[i][j]=i;}else{int p1=f[i][j-1];int p2=f[i+(1<<(j-1))][j-1];if(a[p1]<a[p2]){f[i][j]=p1;}else{f[i][j]=p2;}}}}}int query(int l,int r){if(l>r){swap(l,r);}//if(l==0&&r==1){//cout<<"-------"<<endl;//cout<<p1<<"----"<<p2<<endl;//}if(l==r){return a[f[l][0]];}int k = Log2[r-l+1];int p1 = f[l][k],p2 = f[r-(1<<k)+1][k];//if(l==0&&r==1){//cout<<"-------"<<endl;//cout<<p1<<"----"<<p2<<endl;//}if(a[p1]<a[p2]){return a[p1];}else{return a[p2];}}};int solve(RMQ &q1,RMQ &q2,int x,int n){int Left=-1,Right=-1;int l = x,r=n-1;while(l<=r){int mid = (l+r)/2;int v1 = -q1.query(x,mid),v2=q2.query(x,mid);if(v1==v2){Left = mid;r = mid-1;}else if(v1<v2){l = mid+1;}else{r = mid-1;}}if(Left==-1) return 0;l = Left,r=n-1;while(l<=r){int mid = (l+r)/2;int v1 = -q1.query(x,mid),v2=q2.query(x,mid);//cout<<"MID:"<<mid<<":"<<v1<<"--"<<v2<<endl;if(v1==v2){Right = mid;l = mid+1;}else if(v1<v2){l = mid+1;}else{r = mid-1;}}//cout<<x<<":"<<Left<<","<<Right<<endl;return Right-Left+1;}typedef long long LL;int main(){int n;while(scanf(" %d",&n)==1){vector<int> a1(n),a2(n);for(int i=0;i<n;i++){scanf(" %d",&a1[i]);a1[i]*=-1;}for(int i=0;i<n;i++){scanf(" %d",&a2[i]);}RMQ rmq1(n),rmq2(n);rmq1.init(a1);rmq2.init(a2);LL ret = 0;for(int i=0;i<n;i++){//cout<<"I:"<<i<<endl;ret+=solve(rmq1,rmq2,i,n);}//printf("%I64d\n",ret);cout<<ret<<endl;}return 0;}


0 0
原创粉丝点击