#include <bits/stdc++.h>

using namespace std;
#define rep(i,n) for(int i = 0; i < n; ++i)
#define Rep(i,n) for(int i = 1; i <= n; ++i)
#define lowbit(x) ((x)&(-x))
//#pragma comment(linker,"/STACK:1024000000,1024000000")
#define eps 1e-6
#define sqr(x) ((x)*(x))
#define pb(x) push_back(x)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;
template<class T>inline void rread(T&num){
	num=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
	num*=f;
}
const int inf = 2e9, mod = 1e9 + 7;
const int maxn = 2e5 +50;
const ld PI = acos(-1.0);
ll gcd (ll a, ll b)
{return ( a ? gcd(b%a, a) : b );}
ll power(ll a, ll n)
{ll p = 1;while (n > 0) {if(n%2) {p = p * a;} n >>= 1; a *= a;} return p;}
ll power(ll a, ll n, ll mod)
{ll p = 1;while (n > 0) {if(n%2) {p = p * a; p %= mod;} n >>= 1; a *= a; a %= mod;} return p % mod;}

int n,m,all,k,ch,cm;
int a[maxn],b[maxn];
struct node
{
    int r,l;
    int maxx,minn;
}se[maxn<<2];

void build(int tr,int l,int s)
{
    se[tr].r=s;
    se[tr].l=l;
    int mid=(s+l)/2;
    if(s==l)
    {
        se[tr].maxx=a[s];
        se[tr].minn=b[s];
        return ;
    }
    build(tr*2,l,mid);
    build(tr*2+1,mid+1,s);
    se[tr].maxx=max(se[tr<<1].maxx,se[tr<<1|1].maxx);
    se[tr].minn=min(se[tr<<1].minn,se[tr<<1|1].minn);
    return ;
}

int querymax(int tr,int i,int j)
{
    if(se[tr].l>=i&&se[tr].r<=j)
    {
        return se[tr].maxx;
    }
    int mid=(se[tr].r+se[tr].l)>>1;
    int s1=-inf,s2=-inf;
    if(j<=mid)
        return querymax(tr<<1,i,j);
    else if(i>mid)
        return querymax(tr<<1|1,i,j);
    else return max(querymax(tr<<1,i,j),querymax(tr<<1|1,i,j));
}

int querymin(int tr,int i,int j)
{
    if(se[tr].l>=i&&se[tr].r<=j)
    {
        return se[tr].minn;
    }
    int mid=(se[tr].r+se[tr].l)>>1;
    int s1=inf,s2=inf;
    if(j<=mid)
        return querymin(tr<<1,i,j);
    else if(i>mid)
        return querymin(tr<<1|1,i,j);
    else
        return min(querymin(tr<<1,i,j),querymin(tr<<1|1,i,j));
}
int main()
{
        cin>>n;
        for(int i=1;i<=n;i++)
          cin>>a[i];
        for(int i=1;i<=n;i++)
            cin>>b[i];
        ll sum=0;
        build(1,1,n);

        for(int i=1;i<=n;i++)
        {
            int ml=i,mr=n,minn,maxx;
            int l=i,r=n;
            while(l<=r)
            {
                int mid=(r+l)>>1;
                minn=querymin(1,i,mid);
                maxx=querymax(1,i,mid);
                if(maxx-minn<=0)l=mid+1,mr=mid;
                else r=mid-1;
            }
            l=i,r=n;
            if(a[i]==b[i])ml=i;
            else
            while(l<=r)
            {
                int mid=(r+l)>>1;
                minn=querymin(1,i,mid);
                maxx=querymax(1,i,mid);
                if(maxx-minn>=0)ml=mid,r=mid-1;
                else l=mid+1;
            }//cout<<ml<<" "<<mr<<endl;
            if(querymax(1,i,ml)==querymin(1,i,ml)&&querymax(1,i,mr)==querymin(1,i,mr))
                sum+=mr-ml+1;
        }
        printf("%lld\n",sum);

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define rep(i,n) for(int i = 0; i < n; ++i)
#define Rep(i,n) for(int i = 1; i <= n; ++i)
#define lowbit(x) ((x)&(-x))
//#pragma comment(linker,"/STACK:1024000000,1024000000")
#define eps 1e-6
#define sqr(x) ((x)*(x))
#define pb(x) push_back(x)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;
template<class T>inline void rread(T&num){
	num=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
	num*=f;
}
const int inf = 0x3f3f3f3f, mod = 1e9 + 7;
const int maxn = 2e5 +50;
const ld PI = acos(-1.0);
ll gcd (ll a, ll b)
{return ( a ? gcd(b%a, a) : b );}
ll power(ll a, ll n)
{ll p = 1;while (n > 0) {if(n%2) {p = p * a;} n >>= 1; a *= a;} return p;}
ll power(ll a, ll n, ll mod)
{ll p = 1;while (n > 0) {if(n%2) {p = p * a; p %= mod;} n >>= 1; a *= a; a %= mod;} return p % mod;}

int n,m,all,k,ch,cm;
int a[maxn],b[maxn];
struct node
{
    int r,l;
    int maxx,minn;
}se[maxn<<2];

void build(int tr,int l,int s)
{
    se[tr].r=s;
    se[tr].l=l;
    int mid=(s+l)/2;
    if(s==l)
    {
        se[tr].maxx=a[s];
        se[tr].minn=b[s];
        return ;
    }
    build(tr*2,l,mid);
    build(tr*2+1,mid+1,s);
    se[tr].maxx=max(se[tr<<1].maxx,se[tr<<1|1].maxx);
    se[tr].minn=min(se[tr<<1].minn,se[tr<<1|1].minn);
    return ;
}

int querymax(int tr,int i,int j)
{
    if(se[tr].l>=i&&se[tr].r<=j)
    {
        return se[tr].maxx;
    }
    int mid=(se[tr].r+se[tr].l)/2;
    int s1=-inf,s2=-inf;
    if(i<=mid)
        s1=querymax(tr*2,i,j);
    if(j>mid)
        s2=querymax(tr*2+1,i,j);
    return max(s1,s2);
}

int querymin(int tr,int i,int j)
{
    if(se[tr].l>=i&&se[tr].r<=j)
    {
        return se[tr].minn;
    }
    int mid=(se[tr].r+se[tr].l)/2;
    int s1=inf,s2=inf;
    if(i<=mid)
        s1=querymin(tr*2,i,j);
    if(j>mid)
        s2=querymin(tr*2+1,i,j);
    return min(s1,s2);
}
int main()
{
    rread(n);

        //n=2000;
        for(int i=1;i<=n;i++)
          rread(a[i]);
        for(int i=1;i<=n;i++)
            rread(b[i]);
        //for(int i=1;i<=n;i++)
        //    a[i]=-46709241;
        //for(int j=1;j<=n;j++)
        //    b[j]=-46709241;
        ll sum=0;
        build(1,1,n);

        for(int i=1;i<=n;i++)
        {
            int ml=i,mr=n,minn,maxx;
            int l=i,r=n;
            while(l<=r)
            {
                int mid=(r+l)>>1;
                minn=querymin(1,i,mid);
                maxx=querymax(1,i,mid);
                if(maxx-minn<=0)l=mid+1,mr=mid;
                else r=mid-1;
            }
            l=i,r=n;
            while(l<=r)
            {
                int mid=(r+l)>>1;
                minn=querymin(1,i,mid);
                maxx=querymax(1,i,mid);
                if(maxx-minn>=0)ml=mid,r=mid-1;
                else l=mid+1;
            }//cout<<ml<<" "<<mr<<endl;
            if(querymax(1,i,ml)==querymin(1,i,ml)&&querymax(1,i,mr)==querymin(1,i,mr))
                sum+=mr-ml+1;
        }
        printf("%lld\n",sum);

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define rep(i,n) for(int i = 0; i < n; ++i)
#define Rep(i,n) for(int i = 1; i <= n; ++i)
#define lowbit(x) ((x)&(-x))
//#pragma comment(linker,"/STACK:1024000000,1024000000")
#define eps 1e-6
#define sqr(x) ((x)*(x))
#define pb(x) push_back(x)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;
template<class T>inline void rread(T&num){
	num=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
	num*=f;
}
const int inf = 2e9, mod = 1e9 + 7;
const int maxn = 2e5 +50;
const ld PI = acos(-1.0);
ll gcd (ll a, ll b)
{return ( a ? gcd(b%a, a) : b );}
ll power(ll a, ll n)
{ll p = 1;while (n > 0) {if(n%2) {p = p * a;} n >>= 1; a *= a;} return p;}
ll power(ll a, ll n, ll mod)
{ll p = 1;while (n > 0) {if(n%2) {p = p * a; p %= mod;} n >>= 1; a *= a; a %= mod;} return p % mod;}

int n,m,all,k,ch,cm;
int a[maxn],b[maxn];
struct node
{
    int r,l;
    int maxx,minn;
}se[maxn<<2];

void build(int tr,int l,int s)
{
    se[tr].r=s;
    se[tr].l=l;
    int mid=(s+l)/2;
    if(s==l)
    {
        se[tr].maxx=a[s];
        se[tr].minn=b[s];
        return ;
    }
    build(tr*2,l,mid);
    build(tr*2+1,mid+1,s);
    se[tr].maxx=max(se[tr<<1].maxx,se[tr<<1|1].maxx);
    se[tr].minn=min(se[tr<<1].minn,se[tr<<1|1].minn);
    return ;
}

int querymax(int tr,int i,int j)
{
    if(se[tr].l>=i&&se[tr].r<=j)
    {
        return se[tr].maxx;
    }
    int mid=(se[tr].r+se[tr].l)>>1;
    int s1=-inf,s2=-inf;
    if(j<=mid)
        return querymax(tr<<1,i,j);
    else if(i>mid)
        return querymax(tr<<1|1,i,j);
    else return max(querymax(tr<<1,i,j),querymax(tr<<1|1,i,j));
}

int querymin(int tr,int i,int j)
{
    if(se[tr].l>=i&&se[tr].r<=j)
    {
        return se[tr].minn;
    }
    int mid=(se[tr].r+se[tr].l)>>1;
    int s1=inf,s2=inf;
    if(j<=mid)
        return querymin(tr<<1,i,j);
    else if(i>mid)
        return querymin(tr<<1|1,i,j);
    else
        return min(querymin(tr<<1,i,j),querymin(tr<<1|1,i,j));
}
int main()
{
    rread(n);
        for(int i=1;i<=n;i++)
          rread(a[i]);
        for(int i=1;i<=n;i++)
            rread(b[i]);
        ll sum=0;
        build(1,1,n);

        for(int i=1;i<=n;i++)
        {
            int ml=i,mr=n,minn,maxx;
            int l=i,r=n;
            if(a[n]==b[n])mr=n;
            else
            while(l<=r)
            {
                int mid=(r+l)>>1;
                minn=querymin(1,i,mid);
                maxx=querymax(1,i,mid);
                if(maxx-minn<=0)l=mid+1,mr=mid;
                else r=mid-1;
            }
            l=i,r=n;
            if(a[i]==b[i])ml=i;
            else
            while(l<=r)
            {
                int mid=(r+l)>>1;
                minn=querymin(1,i,mid);
                maxx=querymax(1,i,mid);
                if(maxx-minn>=0)ml=mid,r=mid-1;
                else l=mid+1;
            }//cout<<ml<<" "<<mr<<endl;
            if(querymax(1,i,ml)==querymin(1,i,ml)&&querymax(1,i,mr)==querymin(1,i,mr))
                sum+=mr-ml+1;
        }
        printf("%lld\n",sum);

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define rep(i,n) for(int i = 0; i < n; ++i)
#define Rep(i,n) for(int i = 1; i <= n; ++i)
#define lowbit(x) ((x)&(-x))
//#pragma comment(linker,"/STACK:1024000000,1024000000")
#define eps 1e-6
#define sqr(x) ((x)*(x))
#define pb(x) push_back(x)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;

const int inf = 0x3f3f3f3f, mod = 1e9 + 7;
const int maxn = 2e5 +50;
const ld PI = acos(-1.0);
ll gcd (ll a, ll b)
{return ( a ? gcd(b%a, a) : b );}
ll power(ll a, ll n)
{ll p = 1;while (n > 0) {if(n%2) {p = p * a;} n >>= 1; a *= a;} return p;}
ll power(ll a, ll n, ll mod)
{ll p = 1;while (n > 0) {if(n%2) {p = p * a; p %= mod;} n >>= 1; a *= a; a %= mod;} return p % mod;}

int n,m,all,k,ch,cm;
int a[maxn],b[maxn];
struct node
{
    int r,l;
    int maxx,minn;
}se[maxn<<2];

void build(int tr,int l,int s)
{
    se[tr].r=s;
    se[tr].l=l;
    int mid=(s+l)/2;
    if(s==l)
    {
        se[tr].maxx=a[s];
        se[tr].minn=b[s];
        return ;
    }
    build(tr*2,l,mid);
    build(tr*2+1,mid+1,s);
    se[tr].maxx=max(se[tr<<1].maxx,se[tr<<1|1].maxx);
    se[tr].minn=min(se[tr<<1].minn,se[tr<<1|1].minn);
    return ;
}

int querymax(int tr,int i,int j)
{
    if(se[tr].l>=i&&se[tr].r<=j)
    {
        return se[tr].maxx;
    }
    int mid=(se[tr].r+se[tr].l)/2;
    int s1=-inf,s2=-inf;
    if(i<=mid)
        s1=querymax(tr*2,i,j);
    if(j>mid)
        s2=querymax(tr*2+1,i,j);
    return max(s1,s2);
}

int querymin(int tr,int i,int j)
{
    if(se[tr].l>=i&&se[tr].r<=j)
    {
        return se[tr].minn;
    }
    int mid=(se[tr].r+se[tr].l)/2;
    int s1=inf,s2=inf;
    if(i<=mid)
        s1=querymin(tr*2,i,j);
    if(j>mid)
        s2=querymin(tr*2+1,i,j);
    return min(s1,s2);
}
int main()
{
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&b[i]);
        ll sum=0;
        build(1,1,n);
        for(int i=1;i<n;i++)
        {
            int ml,mr,minn,maxx;
            int l=i-1,r=n+1;
            while(r!=l)
            {
                int mid=r+l>>1;
                minn=querymin(1,i,mid);
                maxx=querymax(1,i,mid);
                if(maxx-minn<0)l=mid+1;
                else r=mid;
            }
            ml=l;
            l=i-1,r=n+1;
            while(r-l>1)
            {
                int mid=r+l>>1;
                minn=querymin(1,i,mid);
                maxx=querymax(1,i,mid);
                if(maxx-minn<=0)l=mid;
                else r=mid;
            }
            mr=l;//cout<<ml<<" "<<mr<<endl;
            if(mr-ml+1>0)
                sum+=mr-ml+1;
        }
        if(a[n]==b[n])
            sum++;
        cout<<sum<<endl;
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define rep(i,n) for(int i = 0; i < n; ++i)
#define Rep(i,n) for(int i = 1; i <= n; ++i)
#define lowbit(x) ((x)&(-x))
//#pragma comment(linker,"/STACK:1024000000,1024000000")
#define eps 1e-6
#define sqr(x) ((x)*(x))
#define pb(x) push_back(x)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;
template<class T>inline void rread(T&num){
	num=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
	num*=f;
}
const int inf = 0x3f3f3f3f, mod = 1e9 + 7;
const int maxn = 2e5 +50;
const ld PI = acos(-1.0);
ll gcd (ll a, ll b)
{return ( a ? gcd(b%a, a) : b );}
ll power(ll a, ll n)
{ll p = 1;while (n > 0) {if(n%2) {p = p * a;} n >>= 1; a *= a;} return p;}
ll power(ll a, ll n, ll mod)
{ll p = 1;while (n > 0) {if(n%2) {p = p * a; p %= mod;} n >>= 1; a *= a; a %= mod;} return p % mod;}

int n,m,all,k,ch,cm;
int a[maxn],b[maxn];
struct node
{
    int r,l;
    int maxx,minn;
}se[maxn<<2];

void build(int tr,int l,int s)
{
    se[tr].r=s;
    se[tr].l=l;
    int mid=(s+l)/2;
    if(s==l)
    {
        se[tr].maxx=a[s];
        se[tr].minn=b[s];
        return ;
    }
    build(tr*2,l,mid);
    build(tr*2+1,mid+1,s);
    se[tr].maxx=max(se[tr<<1].maxx,se[tr<<1|1].maxx);
    se[tr].minn=min(se[tr<<1].minn,se[tr<<1|1].minn);
    return ;
}

int querymax(int tr,int i,int j)
{
    if(se[tr].l>=i&&se[tr].r<=j)
    {
        return se[tr].maxx;
    }
    int mid=(se[tr].r+se[tr].l)/2;
    int s1=-inf,s2=-inf;
    if(i<=mid)
        s1=querymax(tr*2,i,j);
    if(j>mid)
        s2=querymax(tr*2+1,i,j);
    return max(s1,s2);
}

int querymin(int tr,int i,int j)
{
    if(se[tr].l>=i&&se[tr].r<=j)
    {
        return se[tr].minn;
    }
    int mid=(se[tr].r+se[tr].l)/2;
    int s1=inf,s2=inf;
    if(i<=mid)
        s1=querymin(tr*2,i,j);
    if(j>mid)
        s2=querymin(tr*2+1,i,j);
    return min(s1,s2);
}
int main()
{
    rread(n);

        //n=2000;
        for(int i=1;i<=n;i++)
          rread(a[i]);
        for(int i=1;i<=n;i++)
            rread(b[i]);
        //for(int i=1;i<=n;i++)
        //    a[i]=-46709241;
        //for(int j=1;j<=n;j++)
        //    b[j]=-46709241;
        ll sum=0;
        build(1,1,n);

        for(int i=1;i<n;i++)
        {
            int ml,mr,minn,maxx;
            int l=i-1,r=n+1;
            while(r>l)
            {
                int mid=(r+l)/2;
                minn=querymin(1,i,mid);
                maxx=querymax(1,i,mid);
                if(maxx-minn<0)l=mid+1;
                else r=mid;
            }
            ml=l;
            l=i-1,r=n+1;
            while(r-l>1)
            {
                int mid=(r+l)/2;
                minn=querymin(1,i,mid);
                maxx=querymax(1,i,mid);
                if(maxx-minn<=0)l=mid;
                else r=mid;
            }
            mr=l;//cout<<ml<<" "<<mr<<endl;
            if(mr-ml+1>0)
                sum+=mr-ml+1;
        }
        if(a[n]==b[n])
            sum++;
        printf("%lld\n",sum);

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define rep(i,n) for(int i = 0; i < n; ++i)
#define Rep(i,n) for(int i = 1; i <= n; ++i)
#define lowbit(x) ((x)&(-x))
//#pragma comment(linker,"/STACK:1024000000,1024000000")
#define eps 1e-6
#define sqr(x) ((x)*(x))
#define pb(x) push_back(x)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;
template<class T>inline void rread(T&num){
	num=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
	num*=f;
}
const int inf = 2e9, mod = 1e9 + 7;
const int maxn = 2e5 +50;
const ld PI = acos(-1.0);
ll gcd (ll a, ll b)
{return ( a ? gcd(b%a, a) : b );}
ll power(ll a, ll n)
{ll p = 1;while (n > 0) {if(n%2) {p = p * a;} n >>= 1; a *= a;} return p;}
ll power(ll a, ll n, ll mod)
{ll p = 1;while (n > 0) {if(n%2) {p = p * a; p %= mod;} n >>= 1; a *= a; a %= mod;} return p % mod;}

int n,m,all,k,ch,cm;
int a[maxn],b[maxn];
struct node
{
    int r,l;
    int maxx,minn;
}se[maxn<<2];

void build(int tr,int l,int s)
{
    se[tr].r=s;
    se[tr].l=l;
    int mid=(s+l)/2;
    if(s==l)
    {
        se[tr].maxx=a[s];
        se[tr].minn=b[s];
        return ;
    }
    build(tr*2,l,mid);
    build(tr*2+1,mid+1,s);
    se[tr].maxx=max(se[tr<<1].maxx,se[tr<<1|1].maxx);
    se[tr].minn=min(se[tr<<1].minn,se[tr<<1|1].minn);
    return ;
}

int querymax(int tr,int i,int j)
{
    if(se[tr].l>=i&&se[tr].r<=j)
    {
        return se[tr].maxx;
    }
    int mid=(se[tr].r+se[tr].l)>>1;
    int s1=-inf,s2=-inf;
    if(j<=mid)
        return querymax(tr<<1,i,j);
    else if(i>mid)
        return querymax(tr<<1|1,i,j);
    else return max(querymax(tr<<1,i,j),querymax(tr<<1|1,i,j));
}

int querymin(int tr,int i,int j)
{
    if(se[tr].l>=i&&se[tr].r<=j)
    {
        return se[tr].minn;
    }
    int mid=(se[tr].r+se[tr].l)>>1;
    int s1=inf,s2=inf;
    if(j<=mid)
        return querymin(tr<<1,i,j);
    else if(i>mid)
        return querymin(tr<<1|1,i,j);
    else
        return min(querymin(tr<<1,i,j),querymin(tr<<1|1,i,j));
}
int main()
{
        cin>>n;
        for(int i=1;i<=n;i++)
          cin>>a[i];
        for(int i=1;i<=n;i++)
            cin>>b[i];
        ll sum=0;
        build(1,1,n);

        for(int i=1;i<=n;i++)
        {
            int ml=i,mr=n,minn,maxx;
            int l=i,r=n;
            while(l<=r)
            {
                int mid=(r+l)>>1;
                minn=querymin(1,i,mid);
                maxx=querymax(1,i,mid);
                if(maxx-minn<=0)l=mid+1,mr=mid;
                else r=mid-1;
            }
            l=i,r=n;
            while(l<=r)
            {
                int mid=(r+l)>>1;
                minn=querymin(1,i,mid);
                maxx=querymax(1,i,mid);
                if(maxx-minn>=0)ml=mid,r=mid-1;
                else l=mid+1;
            }//cout<<ml<<" "<<mr<<endl;
            if(querymax(1,i,ml)==querymin(1,i,ml)&&querymax(1,i,mr)==querymin(1,i,mr))
                sum+=mr-ml+1;
        }
        printf("%lld\n",sum);

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, 0); //(1) 初期値を最小に -INFかも
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = max(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = 0; //(3) 最大値に関係ない値 -INFかも
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = max(ret, dat[l++]); //(4) 区間の最大値で更新
			if(r & 1) ret = max(ret, dat[--r]); //(4) 区間の最大値で更新
		}
		return ret;
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = min(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = INF; //(3) 最小値に関係ない値
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = min(ret, dat[l++]); //(4) 区間の最小値で更新
			if(r & 1) ret = min(ret, dat[--r]); //(4) 区間の最小値で更新
		}
		return ret;
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	rep(i, n)scanf("%d", &b[i]);
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n) sega.update(i, a[i]);
	rep(i, n) segb.update(i, b[i]);

	ll ret = 0;
	rep(i, n){ // 左端
		// printf("left %d\n", i);
		if(a[i] > b[i]) continue;
		int l = i, r = n;
		int ansl, ansr;

		l = i, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query1 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);
		if(sega.query(i, l) == segb.query(i, l))ansr = l;
		else continue;

		if(i == ansr){
			ret++;
			continue;
		}

		l = i, r = ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);

		ansl = l;
		//[ansl, ansr)までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
ll a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INFF); //(1) 初期値を最小に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最大値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最大値を求める
		if(r <= a || b <= l) return -INFF; //(3) 最大値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return max(vl, vr); //(4) 区間の最大値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INFF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最小値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最小値を求める
		if(r <= a || b <= l) return INFF; //(3) 最小値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return min(vl, vr); //(4) 区間の最小値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%lld", &a[i]);
	rep(i, n)scanf("%lld", &b[i]);
	segtree_max<ll> sega(n);
	segtree_min<ll> segb(n);

	rep(i, n) sega.update(i, a[i]);
	rep(i, n) segb.update(i, b[i]);

	ll ret = 0;
	rep(i, n){ // 左端
		// printf("left %d\n", i);
		int l = i, r = n;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			// printf("%d %d\n", l, r);
		}
		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に -INFかも
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = max(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = -INF; //(3) 最大値に関係ない値 -INFかも
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = max(ret, dat[l++]); //(4) 区間の最大値で更新
			if(r & 1) ret = max(ret, dat[--r]); //(4) 区間の最大値で更新
		}
		return ret;
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = min(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = INF; //(3) 最小値に関係ない値
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = min(ret, dat[l++]); //(4) 区間の最小値で更新
			if(r & 1) ret = min(ret, dat[--r]); //(4) 区間の最小値で更新
		}
		return ret;
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	rep(i, n)scanf("%d", &b[i]);
	segtree_max<int> sega(n + 1);
	segtree_min<int> segb(n + 1);

	rep(i, n) sega.update(i, a[i]);
	sega.update(n, INF + 1); //右端を追加
	rep(i, n) segb.update(i, b[i]);
	segb.update(n, -1); //右端を追加

	ll ret = 0;
	rep(i, n){ // 左端
		int l = i, r = n + 1;
		int ansl, ansr;
		while(r - l > 1){ // lower_bound
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			if(da < db) l = m;
			else r = m;
		}
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n + 1;
		while(r - l > 1){ //upper_bound
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			if(da < db + 1) l = m;
			else r = m;
		}
		ansr = l;
		//[ansl, anrl], .. , [ansl, ansr - 1] までが答えの区間
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に -INFかも
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = max(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = -INF; //(3) 最大値に関係ない値 -INFかも
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = max(ret, dat[l++]); //(4) 区間の最大値で更新
			if(r & 1) ret = max(ret, dat[--r]); //(4) 区間の最大値で更新
		}
		return ret;
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = min(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = INF; //(3) 最小値に関係ない値
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = min(ret, dat[l++]); //(4) 区間の最小値で更新
			if(r & 1) ret = min(ret, dat[--r]); //(4) 区間の最小値で更新
		}
		return ret;
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	rep(i, n)scanf("%d", &b[i]);
	segtree_max<int> sega(n + 1);
	segtree_min<int> segb(n + 1);

	rep(i, n) sega.update(i, a[i]);
	sega.update(n, INF + 1); //右端を追加
	rep(i, n) segb.update(i, b[i]);
	segb.update(n, -1); //右端を追加

	ll ret = 0;
	rep(i, n){ // 左端
		int l = i, r = n + 1;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			// printf("%d %d\n", l, r);
		}

		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n + 1;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db + 1) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最大値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最大値を求める
		if(r <= a || b <= l) return -INF; //(3) 最大値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return max(vl, vr); //(4) 区間の最大値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最小値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最小値を求める
		if(r <= a || b <= l) return INF; //(3) 最小値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return min(vl, vr); //(4) 区間の最小値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

int main(void){
	int n;
	scanf("%d", &n);
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n){
		int t; scanf("%d", &t);
		sega.update(i, t);
	}
	rep(i, n){
		int t; scanf("%d", &t);
		segb.update(i, t);
	}

	ll ret = 0;
	rep(i, n){ // 左端
		// printf("left %d\n", i);
		int l = i, r = n;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			// printf("%d %d\n", l, r);
		}
		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最大値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最大値を求める
		if(r <= a || b <= l) return -INF; //(3) 最大値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return max(vl, vr); //(4) 区間の最大値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最小値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最小値を求める
		if(r <= a || b <= l) return INF; //(3) 最小値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return min(vl, vr); //(4) 区間の最小値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

int main(void){
	int n;
	scanf("%d", &n);
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n){
		int t; scanf("%d", &t);
		sega.update(i, t);
	}
	rep(i, n){
		int t; scanf("%d", &t);
		segb.update(i, t);
	}

	ll ret = 0;
	rep(i, n){ // 左端
		int l = i, r = n;
		int ansl, ansr;

		l = i, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			if(da <= db) l = m;
			else r = m;
		}
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansr = l;
		else continue;
		ansr = l;

		l = i, r = ansr
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			if(da < db) l = m;
			else r = m;
		}
		ansl = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に -INFかも
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = max(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = -INF; //(3) 最大値に関係ない値 -INFかも
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = max(ret, dat[l++]); //(4) 区間の最大値で更新
			if(r & 1) ret = max(ret, dat[--r]); //(4) 区間の最大値で更新
		}
		return ret;
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = min(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = INF; //(3) 最小値に関係ない値
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = min(ret, dat[l++]); //(4) 区間の最小値で更新
			if(r & 1) ret = min(ret, dat[--r]); //(4) 区間の最小値で更新
		}
		return ret;
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	rep(i, n)scanf("%d", &b[i]);
	if(n == 1){
		if(a[0] == b[0]) printf("1\n");
		else printf("0\n");
		return 0;
	}
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n) sega.update(i, a[i]);
	sega.update(n, INF + 1);
	rep(i, n) segb.update(i, b[i]);
	segb.update(n, -1);

	ll ret = 0;
	rep(i, n){ // 左端
		// if(a[i] > b[i]) continue;
		// printf("left %d\n", i);
		int l = i, r = n + 1;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			// printf("%d %d\n", l, r);
		}

		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n + 1;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db + 1) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に -INFかも
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = max(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = -INF; //(3) 最大値に関係ない値 -INFかも
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = max(ret, dat[l++]); //(4) 区間の最大値で更新
			if(r & 1) ret = max(ret, dat[--r]); //(4) 区間の最大値で更新
		}
		return ret;
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = min(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = INF; //(3) 最小値に関係ない値
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = min(ret, dat[l++]); //(4) 区間の最小値で更新
			if(r & 1) ret = min(ret, dat[--r]); //(4) 区間の最小値で更新
		}
		return ret;
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	rep(i, n)scanf("%d", &b[i]);
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n) sega.update(i, a[i]);
	sega.update(n, INF + 1);
	rep(i, n) segb.update(i, b[i]);
	segb.update(n, -1);

	ll ret = 0;
	rep(i, n){ // 左端
		if(a[i] > b[i]) continue;
		// printf("left %d\n", i);
		int l = i, r = n + 1;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			// printf("%d %d\n", l, r);
		}

		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n + 1;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db + 1) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
ll a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最大値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最大値を求める
		if(r <= a || b <= l) return -INF; //(3) 最大値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return max(vl, vr); //(4) 区間の最大値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最小値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最小値を求める
		if(r <= a || b <= l) return INF; //(3) 最小値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return min(vl, vr); //(4) 区間の最小値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%lld", &a[i]);
	rep(i, n)scanf("%lld", &b[i]);
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n) sega.update(i, a[i]);
	rep(i, n) segb.update(i, b[i]);

	ll ret = 0;
	rep(i, n){ // 左端
		// printf("left %d\n", i);
		int l = i, r = n;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			// printf("%d %d\n", l, r);
		}
		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に -INFかも
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = max(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = -INF; //(3) 最大値に関係ない値 -INFかも
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = max(ret, dat[l++]); //(4) 区間の最大値で更新
			if(r & 1) ret = max(ret, dat[--r]); //(4) 区間の最大値で更新
		}
		return ret;
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = min(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = INF; //(3) 最小値に関係ない値
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = min(ret, dat[l++]); //(4) 区間の最小値で更新
			if(r & 1) ret = min(ret, dat[--r]); //(4) 区間の最小値で更新
		}
		return ret;
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	rep(i, n)scanf("%d", &b[i]);
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n) sega.update(i, a[i]);
	rep(i, n) segb.update(i, b[i]);

	ll ret = 0;
	rep(i, n){ // 左端
		// printf("left %d\n", i);
		if(a[i] > b[i]) continue;
		int l = i, r = n;
		int ansl, ansr;

		l = i, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query1 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);
		if(sega.query(i, l) == segb.query(i, l))ansr = l;
		else continue;

		if(i == ansr){
			ret++;
			continue;
		}

		l = i, r = ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);

		ansl = l;
		//[ansl, ansr)までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に -INFかも
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = max(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = -INF; //(3) 最大値に関係ない値 -INFかも
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = max(ret, dat[l++]); //(4) 区間の最大値で更新
			if(r & 1) ret = max(ret, dat[--r]); //(4) 区間の最大値で更新
		}
		return ret;
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = min(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = INF; //(3) 最小値に関係ない値
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = min(ret, dat[l++]); //(4) 区間の最小値で更新
			if(r & 1) ret = min(ret, dat[--r]); //(4) 区間の最小値で更新
		}
		return ret;
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	rep(i, n)scanf("%d", &b[i]);
	if(n == 1){
		if(a[0] == b[0]) printf("1\n");
		else printf("0\n");
		return 0;
	}
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n) sega.update(i, a[i]);
	sega.update(n, INF + 1);
	rep(i, n) segb.update(i, b[i]);
	segb.update(n, -1);

	ll ret = 0;
	rep(i, n){ // 左端
		if(a[i] > b[i]) continue;
		// printf("left %d\n", i);
		int l = i, r = n + 1;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			// printf("%d %d\n", l, r);
		}

		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n + 1;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db + 1) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に -INFかも
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = max(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = -INF; //(3) 最大値に関係ない値 -INFかも
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = max(ret, dat[l++]); //(4) 区間の最大値で更新
			if(r & 1) ret = max(ret, dat[--r]); //(4) 区間の最大値で更新
		}
		return ret;
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = min(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = INF; //(3) 最小値に関係ない値
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = min(ret, dat[l++]); //(4) 区間の最小値で更新
			if(r & 1) ret = min(ret, dat[--r]); //(4) 区間の最小値で更新
		}
		return ret;
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	rep(i, n)scanf("%d", &b[i]);
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n) sega.update(i, a[i]);
	rep(i, n) segb.update(i, b[i]);

	ll ret = 0;
	rep(i, n){ // 左端
		// printf("left %d\n", i);
		int l = i, r = n;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			// printf("%d %d\n", l, r);
		}
		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
ll a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, 0); //(1) 初期値を最小に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最大値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最大値を求める
		if(r <= a || b <= l) return 0; //(3) 最大値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return max(vl, vr); //(4) 区間の最大値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INFF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最小値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最小値を求める
		if(r <= a || b <= l) return INFF; //(3) 最小値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return min(vl, vr); //(4) 区間の最小値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%lld", &a[i]);
	rep(i, n)scanf("%lld", &b[i]);
	segtree_max<ll> sega(n);
	segtree_min<ll> segb(n);

	rep(i, n) sega.update(i, a[i]);
	rep(i, n) segb.update(i, b[i]);

	ll ret = 0;
	rep(i, n){ // 左端
		// printf("left %d\n", i);
		int l = i, r = n;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			// printf("%d %d\n", l, r);
		}
		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に -INFかも
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = max(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = -INF; //(3) 最大値に関係ない値 -INFかも
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = max(ret, dat[l++]); //(4) 区間の最大値で更新
			if(r & 1) ret = max(ret, dat[--r]); //(4) 区間の最大値で更新
		}
		return ret;
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = min(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = INF; //(3) 最小値に関係ない値
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = min(ret, dat[l++]); //(4) 区間の最小値で更新
			if(r & 1) ret = min(ret, dat[--r]); //(4) 区間の最小値で更新
		}
		return ret;
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	rep(i, n)scanf("%d", &b[i]);
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n) sega.update(i, a[i]);
	rep(i, n) segb.update(i, b[i]);

	ll ret = 0;
	rep(i, n){ // 左端
		if(a[i] <= b[i]) continue;
		// printf("left %d\n", i);
		int l = i, r = n;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			// printf("%d %d\n", l, r);
		}
		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : table[][]の中身の型
class SparseTable_max{
public:
	int N, M; //table[N][M]
	// table[i][k] := [i, i + 2^k)の最大値
	vector<vector<T>> table;
	template<class S> SparseTable_max(int n, S &val): N(n){ // O(nlogn)
		M = 32 - __builtin_clz(N); // M - 1 <= logN < M
		table.resize(N, vector<T>(M));
		for (int i = 0; i < N; ++i){ // [i, i + 1)までの区間の最大値
			table[i][0] = val[i];
		}
		for (int k = 0; k < M - 1; ++k){ // [i, i + 2^(k+1))の区間を計算
			for (int i = 0; i + (1<< k) < N; ++i){
				// iから2^(k+1)の長さの区間の最小値を2^kの長さの区間の最大値を利用して求める
				table[i][k + 1] = max(table[i][k], table[i + (1 << k)][k]); // (1)最大値
			}
		}
	}
	T query(int l, int r){ // O(1) [l, r) の間の最大値
		int k = 31 - __builtin_clz(r - l); //区間の長さの半分以上の値 （k<= r - l < k + 1)
		return max(table[l][k], table[r - (1 << k)][k]); // (2) 最大値
	}
};

template <class T> //T : table[][]の中身の型
class SparseTable_min{
public:
	int N, M; //table[N][M]
	// table[i][k] := [i, i + 2^k)の最小値
	vector<vector<T>> table;
	template<class S> SparseTable_min(int n, S &val): N(n){ // O(nlogn)
		M = 32 - __builtin_clz(N); // M - 1 <= logN < M
		table.resize(N, vector<T>(M));
		for (int i = 0; i < N; ++i){ // [i, i + 1)までの区間の最小値
			table[i][0] = val[i];
		}
		for (int k = 0; k < M - 1; ++k){ // [i, i + 2^(k+1))の区間を計算
			for (int i = 0; i + (1<< k) < N; ++i){
				// iから2^(k+1)の長さの区間の最小値を2^kの長さの区間の最小値を利用して求める
				table[i][k + 1] = min(table[i][k], table[i + (1 << k)][k]); // (1)最小値
			}
		}
	}
	T query(int l, int r){ // O(1) [l, r) の間の最小値
		int k = 31 - __builtin_clz(r - l); //区間の長さの半分以上の値 （k<= r - l < k + 1)
		return min(table[l][k], table[r - (1 << k)][k]); // (2) 最小値
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	a[n] = INF + 1;
	rep(i, n)scanf("%d", &b[i]);
	b[n] = -1;
	SparseTable_max<int> sega(n + 1, a);
	SparseTable_min<int> segb(n + 1, b);

	ll ret = 0;
	rep(i, n){ // 左端
		int l = i, r = n + 1;
		int ansl, ansr;
		while(r - l > 1){ // lower_bound
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			if(da < db) l = m;
			else r = m;
		}
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n + 1;
		while(r - l > 1){ //upper_bound
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			if(da < db + 1) l = m;
			else r = m;
		}
		ansr = l;
		//[ansl, anrl], .. , [ansl, ansr - 1] までが答えの区間
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に -INFかも
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = max(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = -INF; //(3) 最大値に関係ない値 -INFかも
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = max(ret, dat[l++]); //(4) 区間の最大値で更新
			if(r & 1) ret = max(ret, dat[--r]); //(4) 区間の最大値で更新
		}
		return ret;
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = min(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = INF; //(3) 最小値に関係ない値
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = min(ret, dat[l++]); //(4) 区間の最小値で更新
			if(r & 1) ret = min(ret, dat[--r]); //(4) 区間の最小値で更新
		}
		return ret;
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	rep(i, n)scanf("%d", &b[i]);
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n) sega.update(i, a[i]);
	rep(i, n) segb.update(i, b[i]);

	ll ret = 0;
	rep(i, n){ // 左端
		if(a[i] > b[i]) continue;
		// printf("left %d\n", i);
		int l = i, r = n;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			// printf("%d %d\n", l, r);
		}
		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最大値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最大値を求める
		if(r <= a || b <= l) return -INF; //(3) 最大値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return max(vl, vr); //(4) 区間の最大値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最小値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最小値を求める
		if(r <= a || b <= l) return INF; //(3) 最小値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return min(vl, vr); //(4) 区間の最小値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

int main(void){
	int n;
	scanf("%d", &n);
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n){
		int t; scanf("%d", &t);
		sega.update(i, t);
	}
	rep(i, n){
		int t; scanf("%d", &t);
		segb.update(i, t);
	}

	ll ret = 0;
	rep(i, n){ // 左端
		// printf("left %d\n", i);
		int l = i, r = n;
		int ansl, ansr;

		l = i, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query1 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);
		if(sega.query(i, l) == segb.query(i, l))ansr = l;
		else continue;

		l = i, r = ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);

		ansl = l;
		//[ansl, ansr)までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
ll a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最大値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最大値を求める
		if(r <= a || b <= l) return -INF; //(3) 最大値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return max(vl, vr); //(4) 区間の最大値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最小値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最小値を求める
		if(r <= a || b <= l) return INF; //(3) 最小値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return min(vl, vr); //(4) 区間の最小値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%lld", &a[i]);
	rep(i, n)scanf("%lld", &b[i]);
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n) sega.update(i, a[i]);
	rep(i, n) segb.update(i, b[i]);

	ll ret = 0;
	rep(i, n){ // 左端
		// printf("left %d\n", i);
		int l = i, r = n;
		int ansl, ansr;

		l = i, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query1 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);
		if(sega.query(i, l) == segb.query(i, l))ansr = l;
		else continue;

		l = i, r = ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);

		ansl = l;
		//[ansl, ansr)までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に -INFかも
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = max(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = -INF; //(3) 最大値に関係ない値 -INFかも
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = max(ret, dat[l++]); //(4) 区間の最大値で更新
			if(r & 1) ret = max(ret, dat[--r]); //(4) 区間の最大値で更新
		}
		return ret;
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = min(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = INF; //(3) 最小値に関係ない値
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = min(ret, dat[l++]); //(4) 区間の最小値で更新
			if(r & 1) ret = min(ret, dat[--r]); //(4) 区間の最小値で更新
		}
		return ret;
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	rep(i, n)scanf("%d", &b[i]);
	if(n == 1){
		if(a[0] == b[0]) printf("1\n");
		else printf("0\n");
		return 0;
	}
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n) sega.update(i, a[i]);
	sega.update(n, INF + 1);
	rep(i, n) segb.update(i, b[i]);
	segb.update(n, -1);

	ll ret = 0;
	rep(i, n){ // 左端
		if(a[i] > b[i]) continue;
		// printf("left %d\n", i);
		int l = i, r = n + 1;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			printf("%d %d\n", l, r);
		}

		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n + 1;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db + 1) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
ll a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, 0); //(1) 初期値を最小に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最大値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最大値を求める
		if(r <= a || b <= l) return 0; //(3) 最大値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return max(vl, vr); //(4) 区間の最大値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INFF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		k += n - 1; //葉の節点
		dat[k] = val;
		while(k > 0){
			k = (k - 1) / 2;
			dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]); // (2) 区間の最小値で更新
		}
	}
	T query(int a, int b, int k, int l, int r){ //[a, b)の最小値を求める
		if(r <= a || b <= l) return INFF; //(3) 最小値に関係ない値で更新
		if(a <= l && r <= b) return dat[k];
		else{
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return min(vl, vr); //(4) 区間の最小値で更新
		}
	}
	T query(int a, int b){
		return query(a, b, 0, 0, n);
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%lld", &a[i]);
	rep(i, n)scanf("%lld", &b[i]);
	segtree_max<ll> sega(n);
	segtree_min<ll> segb(n);

	rep(i, n) sega.update(i, a[i]);
	rep(i, n) segb.update(i, b[i]);

	ll ret = 0;
	rep(i, n){ // 左端
		// printf("left %d\n", i);
		int l = i, r = n;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query %lld %lld\n", sega.query(i, l), segb.query(i, l));
		if(sega.query(i, l) == segb.query(i, l))ansl = l;
		else continue;

		l = ansl, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			if(da <= db + 1) l = m;
			else r = m;
		}
		ansr = r;
		// printf("%d %d\n", ansl, ansr);
		ret += ansr - ansl + 1;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=n-1;i>=(0);i--)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define eall(v) unique(all(v), v.end())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;
const ll INFF = 1e18;

int n;
int a[200010], b[200010];

template <class T> //T : dat[]の中身の型
class segtree_max{
public:
	int n;
	vector<T> dat;
	segtree_max(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, -INF); //(1) 初期値を最小に -INFかも
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = max(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = -INF; //(3) 最大値に関係ない値 -INFかも
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = max(ret, dat[l++]); //(4) 区間の最大値で更新
			if(r & 1) ret = max(ret, dat[--r]); //(4) 区間の最大値で更新
		}
		return ret;
	}
};

template <class T> //T : dat[]の中身の型
class segtree_min{
public:
	int n;
	vector<T> dat;
	segtree_min(int n_): n(n_){ //n_要素数
		n = 1;
		while(n < n_) n *= 2;
		dat.resize(n * 2, INF); //(1) 初期値を最大に
	}
	void update(int k, T val){ // k番目の値(0-indexed)を val に変更
		for (dat[k += n] = val; k > 0; k >>= 1){ // kを含む区間のインデックスを下から順に列挙
			dat[k>>1] = min(dat[k], dat[k ^ 1]); // (2) 区間の最大値で更新
		}
	}
	T query(int l, int r){
		T ret = INF; //(3) 最小値に関係ない値
		for (l += n, r += n; l < r; l >>= 1, r >>= 1){
			if(l & 1) ret = min(ret, dat[l++]); //(4) 区間の最小値で更新
			if(r & 1) ret = min(ret, dat[--r]); //(4) 区間の最小値で更新
		}
		return ret;
	}
};

int main(void){
	scanf("%d", &n);
	rep(i, n)scanf("%d", &a[i]);
	rep(i, n)scanf("%d", &b[i]);
	segtree_max<int> sega(n);
	segtree_min<int> segb(n);

	rep(i, n) sega.update(i, a[i]);
	rep(i, n) segb.update(i, b[i]);

	ll ret = 0;
	rep(i, n){ // 左端
		if(a[i] >= b[i]) continue;
		// printf("left %d\n", i);
		int l = i, r = n;
		int ansl, ansr;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da < db) l = m;
			else r = m;
			// printf("%d %d\n", l, r);
		}
		// printf("query1 %lld %lld %d %d\n", sega.query(i, l + 1), segb.query(i, l + 1), l, r);
		if(sega.query(i, l + 1) == segb.query(i, l + 1))ansl = l;
		else continue;

		l = ansl, r = n;
		while(r - l > 1){
			int m = (l + r) / 2;
			auto da = sega.query(i, m); //単調増加
			auto db = segb.query(i, m); //単調減少
			// printf("m : %d %lld %lld\n", m, da, db);
			if(da <= db) l = m;
			else r = m;
		}
		// printf("query2 %lld %lld %d %d\n", sega.query(i, l), segb.query(i, l), l, r);

		ansr = l;
		//[ansl, ansr]までが左端の範囲
		// printf("ans %d %d\n", ansl, ansr);
		ret += ansr - ansl;
	}
	printf("%lld\n", ret);
	return 0;
}


#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <sstream>
#include <cmath>
#include <set>
#include <iomanip>
using namespace std;

#define REP(i,n) for(int (i)=0;(i)<(int)(n);(i)++)
#define REMOVE(Itr,n) (Itr).erase(remove((Itr).begin(),(Itr).end(),n),(Itr).end())
#define RREP(i,n) for(int (i)=(int)(n)-1;i>=0;i--)
typedef long long ll;

template<class T> struct SparseTableMin {
   int N;
   vector<int> log_table;
   vector<T> val;
   vector< vector<int> > table;
   SparseTableMin (vector<T> &A) : N(A.size()), log_table(A.size()+1,0) ,val(A) {
    for (int i = 2; i <= N; i++) log_table[i] = log_table[i>>1] + 1;
    table.resize(log_table[N]+1, vector<int>(N));
    val.assign(A.begin(),A.end());
    for (int i = 0; i < N; i++) table[0][i] = i;
    for (int k = 0; k < log_table[N]; k++) {
      for (int i = 0; i + (1 << k) < N; i++) {
        int l = table[k][i];
        int r = table[k][i+(1<<k)];
        table[k+1][i] = (A[l] < A[r]) ? l : r;
      }
    }
   }
   int get_min_index(int l, int r) {
    int k = log_table[r-l+1];
    int idxl = table[k][l];
    int idxr = table[k][r-(1<<k)];
    if (val[idxl] < val[idxr]) return idxl;
    return idxr;
   }
};

template<class T> struct SparseTableMax {
   int N;
   vector<int> log_table;
   vector<T> val;
   vector< vector<int> > table;
   SparseTableMax (vector<T> &A) : N(A.size()), log_table(A.size()+1,0) ,val(A) {
    for (int i = 2; i <= N; i++) log_table[i] = log_table[i>>1] + 1;
    table.resize(log_table[N]+1, vector<int>(N));
    val.assign(A.begin(),A.end());
    for (int i = 0; i < N; i++) table[0][i] = i;
    for (int k = 0; k < log_table[N]; k++) {
      for (int i = 0; i + (1 << k) < N; i++) {
        int l = table[k][i];
        int r = table[k][i+(1<<k)];
        table[k+1][i] = (A[l] > A[r]) ? l : r;
      }
    }
   }
   int get_max_index(int l, int r) {
    int k = log_table[r-l];
    int idxl = table[k][l];
    int idxr = table[k][r-(1<<k)];
    if (val[idxl] > val[idxr]) return idxl;
    return idxr;
   }
};

int main() {

  int N; cin >> N;
  vector<ll> a(N),b(N);
  REP(i,N) cin >> a[i];
  REP(i,N) cin >> b[i];

  SparseTableMax<ll> A(a);
  SparseTableMin<ll> B(b);

  ll ans = 0;
  REP(i,N) {
    int l1 = i, r1 = N;
    while(r1 - l1 > 1) {
      int mid = (l1 + r1) / 2;
      int v1 = A.get_max_index(i,mid);
      int v2 = B.get_min_index(i,mid);
      if(a[v1] > b[v2]) l1 = mid;
      else r1 = mid;
    }
    int l2 = i, r2 = N;
    while(r2 - l2 > 1) {
      int mid = (l2 + r2) / 2;
      int v1 = A.get_max_index(i,mid);
      int v2 = B.get_min_index(i,mid);
      if(a[v1] >= b[v2]) l2 = mid;
      else r2 = mid;
    }
    if(l1 == l2) {
      if(a[l1] == b[l2]) ans++;
    } else ans += l2 - l1 + 1;
  }

  cout << ans << endl;

  return 0;
}


#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <sstream>
#include <cmath>
#include <set>
#include <iomanip>
using namespace std;

#define REP(i,n) for(int (i)=0;(i)<(int)(n);(i)++)
#define REMOVE(Itr,n) (Itr).erase(remove((Itr).begin(),(Itr).end(),n),(Itr).end())
#define RREP(i,n) for(int (i)=(int)(n)-1;i>=0;i--)
typedef long long ll;

template<class T> struct SparseTableMin {
   int N;
   vector<int> log_table;
   vector<T> val;
   vector< vector<int> > table;
   SparseTableMin (vector<T> &A) : N(A.size()), log_table(A.size()+1,0) ,val(A) {
    for (int i = 2; i <= N; i++) log_table[i] = log_table[i>>1] + 1;
    table.resize(log_table[N]+1, vector<int>(N));
    for (int i = 0; i < N; i++) table[0][i] = i;
    for (int k = 1; (1<<k) <= N; k++) {
      for (int i = 0; i + (1 << k) <= N; i++) {
        int l = table[k-1][i];
        int r = table[k-1][i+(1<<(k-1))];
        table[k][i] = (val[l] < val[r]) ? l : r;
      }
    }
   }
   int get_min_index(int l, int r) {
    int k = log_table[r-l+1];
    int idxl = table[k][l];
    int idxr = table[k][r+1-(1<<k)];
    if (val[idxl] < val[idxr]) return idxl;
    return idxr;
   }
};

template<class T> struct SparseTableMax {
   int N;
   vector<int> log_table;
   vector<T> val;
   vector< vector<int> > table;
   SparseTableMax (vector<T> &A) : N(A.size()), log_table(A.size()+1,0) ,val(A) {
    for (int i = 2; i <= N; i++) log_table[i] = log_table[i>>1] + 1;
    table.resize(log_table[N]+1, vector<int>(N));
    for (int i = 0; i < N; i++) table[0][i] = i;
    for (int k = 1; (1<<k) <= N; k++) {
      for (int i = 0; i + (1 << k) <= N; i++) {
        int l = table[k-1][i];
        int r = table[k-1][i+(1<<(k-1))];
        table[k][i] = (val[l] > val[r]) ? l : r;
      }
    }
   }
   int get_max_index(int l, int r) {
    int k = log_table[r-l+1];
    int idxl = table[k][l];
    int idxr = table[k][r+1-(1<<k)];
    if (val[idxl] > val[idxr]) return idxl;
    return idxr;
   }
};

int main() {

  int N; cin >> N;
  vector<ll> a(N),b(N);
  REP(i,N) cin >> a[i];
  REP(i,N) cin >> b[i];

  SparseTableMax<ll> A(a);
  SparseTableMin<ll> B(b);

  ll ans = 0;
  REP(i,N) {
    int l1 = i, r1 = N;
    while(r1 - l1 > 1) {
      int mid = (l1 + r1) / 2;
      int v1 = A.get_max_index(i,mid);
      int v2 = B.get_min_index(i,mid);
      if(a[v1] > b[v2]) l1 = mid;
      else r1 = mid;
    }
    int l2 = i, r2 = N;
    while(r2 - l2 > 1) {
      int mid = (l2 + r2) / 2;
      int v1 = A.get_max_index(i,mid);
      int v2 = B.get_min_index(i,mid);
      if(a[v1] >= b[v2]) l2 = mid;
      else r2 = mid;
    }
    ans += l2 - l1;
  }

  cout << ans << endl;

  return 0;
}


#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <sstream>
#include <cmath>
#include <set>
#include <iomanip>
using namespace std;

#define REP(i,n) for(int (i)=0;(i)<(int)(n);(i)++)
#define REMOVE(Itr,n) (Itr).erase(remove((Itr).begin(),(Itr).end(),n),(Itr).end())
#define RREP(i,n) for(int (i)=(int)(n)-1;i>=0;i--)
typedef long long ll;

template<class T> struct SparseTableMin {

   int N;
   vector<T> val;
   vector<int> log_table;
   vector< vector<int> > table;

   SparseTableMin (vector<T> &A) : N(A.size()), log_table(A.size()+1,0) ,val(A) {
    for (int i = 2; i <= N; i++) log_table[i] = log_table[i>>1] + 1;
    table.resize(log_table[N]+1, vector<int>(N));
    for (int i = 0; i < N; i++) table[0][i] = i;
    for (int k = 0; k < log_table[N] - 1; k++) {
      for (int i = 0; i + (1 << k) < N; i++) {
        int l = table[k][i];
        int r = table[k][i+(1<<k)];
        table[k+1][i] = (val[l] <= val[r]) ? l : r;
      }
    }
   }

   int get_min_index(int l, int r) {
    int k = log_table[r-l];
    int idxl = table[k][l];
    int idxr = table[k][r-(1<<k)];
    return val[idxl] <= val[idxr] ? idxl : idxr;
   }

};

template<class T> struct SparseTableMax {

   int N;
   vector<T> val;
   vector<int> log_table;
   vector< vector<int> > table;

   SparseTableMax (vector<T> &A) : N(A.size()), log_table(A.size()+1,0) ,val(A) {
    for (int i = 2; i <= N; i++) log_table[i] = log_table[i>>1] + 1;
    table.resize(log_table[N]+1, vector<int>(N));
    for (int i = 0; i < N; i++) table[0][i] = i;
    for (int k = 0; k < log_table[N] - 1; k++) {
      for (int i = 0; i + (1 << k) < N; i++) {
        int l = table[k][i];
        int r = table[k][i+(1<<k)];
        table[k+1][i] = (val[l] >= val[r]) ? l : r;
      }
    }
   }

   int get_max_index(int l, int r) {
    int k = log_table[r-l];
    int idxl = table[k][l];
    int idxr = table[k][r-(1<<k)];
    return val[idxl] >= val[idxr] ? idxl : idxr;
   }

};

int main() {

  int N; cin >> N;
  vector<ll> a(N),b(N);
  REP(i,N) cin >> a[i];
  REP(i,N) cin >> b[i];

  SparseTableMax<ll> A(a);
  SparseTableMin<ll> B(b);

  ll ans = 0;
  REP(i,N) {
    int l1 = i, r1 = N;
    while(r1 - l1 > 1) {
      int mid = (l1 + r1) / 2;
      int v1 = A.get_max_index(i,mid);
      int v2 = B.get_min_index(i,mid);
      if(a[v1] < b[v2]) l1 = mid;
      else r1 = mid;
    }
    int l2 = i, r2 = N;
    while(r2 - l2 > 1) {
      int mid = (l2 + r2) / 2;
      int v1 = A.get_max_index(i,mid);
      int v2 = B.get_min_index(i,mid);
      if(a[v1] <= b[v2]) l2 = mid;
      else r2 = mid;
    }
    ans += l2 - l1;
  }

  cout << ans << endl;

  return 0;
}


#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <sstream>
#include <cmath>
#include <set>
#include <iomanip>
#include <deque>
#include <stdio.h>
#include <fstream>
using namespace std;

#define REP(i,n) for(int (i)=0;(i)<(int)(n);(i)++)
#define RREP(i,n) for(int (i)=(int)(n)-1;i>=0;i--)
#define FILL(Itr,n) fill((Itr).begin(),(Itr).end(),n)
#define REMOVE(Itr,n) (Itr).erase(remove((Itr).begin(),(Itr).end(),n),(Itr).end())
#define UNIQUE(Itr) sort((Itr).begin(),(Itr).end()); (Itr).erase(unique((Itr).begin(),(Itr).end()),(Itr).end())
#define LBOUND(Itr,val) lower_bound((Itr).begin(),(Itr).end(),(val))
#define UBOUND(Itr,val) upper_bound((Itr).begin(),(Itr).end(),(val))
#define MOD 1000000007
typedef long long ll;
typedef pair<int,int> P;

template <class T> class SegmentTree {
private:
    vector<T> segtree_min;
    vector<T> segtree_max;
    const int N = 1<<19;
    const T limit_max = 1e9;
    const T limit_min = -1e9;
public:
    SegmentTree(){
        segtree_max = *new vector<T>(N*2,limit_min);
        segtree_min = *new vector<T>(N*2,limit_max);
    }
    void update(int idx, T val){
        idx += N-1;
        segtree_max[idx] = segtree_min[idx] = val;
        while(idx){
            idx = (idx-1)/2;
            segtree_max[idx] = max(segtree_max[idx*2+1],segtree_max[idx*2+2]);
            segtree_min[idx] = min(segtree_min[idx*2+1],segtree_min[idx*2+2]);
        }
    }
    T getmax(int a, int b) { return query_max(a,b,0,0,N); }
    T getmin(int a, int b) { return query_min(a,b,0,0,N); }
    T query_max(int a,int b,int k,int l,int r){
        if(r <= a || b <= l) return limit_min;
        if(a <= l && r <= b) return segtree_max[k];
        T vl = query_max(a,b,k*2+1,l,(l+r)/2);
        T vr = query_max(a,b,k*2+2,(l+r)/2,r);
        return max(vl,vr);
    }
    T query_min(int a,int b,int k,int l,int r){
        if(r <= a || b <= l) return limit_max;
        if(a <= l && r <= b) return segtree_min[k];
        T vl = query_min(a,b,k*2+1,l,(l+r)/2);
        T vr = query_min(a,b,k*2+2,(l+r)/2,r);
        return min(vl,vr);
    }
};

SegmentTree<int> a,b;
int aa[200010],bb[200010];

bool judge1(int x, int s){
    int va = a.getmax(s,x+1);
    int vb = b.getmin(s,x+1);
    if(va==vb)return true;
    return false;
}

int BinarySearchHighest(int low, int high){
    int start = low;
    while(high-low>1){
        int mid=(low+high)/2;
        if(judge1(mid,start))low = mid;
        else high = mid;
    }
    return low;
}

bool judge2(int x, int s){
    int va = a.getmax(x+1,s);
    int vb = b.getmin(x+1,s);
    if(va==vb)return true;
    return false;
}

int BinarySearchLowest(int low, int high){
    int start = high+1;
    while(high-low>1){
        int mid=(low+high)/2;
        if(judge2(mid,start))high = mid;
        else low = mid;
    }
    return high;
}

int main(){

    int n; cin>>n;
    REP(i,n)cin>>aa[i];
    REP(i,n)cin>>bb[i];

    REP(i,n){
        a.update(i,aa[i]);
        b.update(i,bb[i]);
    }

    ll ans = 0;
    REP(i,n){
        if(a.getmax(i,i+1)==b.getmax(i,i+1)){
            int L = BinarySearchLowest(-1,i)+1;
            int R = BinarySearchHighest(i,n);
            ans += L + R - 2*i + 1;
            //cout<<i<<" "<<L<<" "<<R<<endl;
        }
    }

    cout<<ans<<endl;

    return 0;
}