codeforces 689D
2016-07-25 10:59
387 查看
题意:给出两个序列,计算有多少个区间,第一个序列的最大值等于第二个序列的最小值。
题解:注意到第一个区间的最大值递增,第二个区间的最小值递减。我们可以枚举起点,二分相等位置。
#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
+1));
}
RMQ(){
}
void init(const vector<int> &a){
this->a=a;
for(int j=0;j<=Log2
;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;
}
题解:注意到第一个区间的最大值递增,第二个区间的最小值递减。我们可以枚举起点,二分相等位置。
#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
+1));
}
RMQ(){
}
void init(const vector<int> &a){
this->a=a;
for(int j=0;j<=Log2
;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;
}
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法