Continuous Intervals segment tree

 

Meaning of the questions: given a sequence ai

Lr satisfies asked how many of the number of sort between a [l] -a [r] at a [l] -a [r] the difference between adjacent digital difference is not greater than 1

 

Very clever tree line when the game simply lacks clue

 

For each L and may need to be modified so maintenance can be carried out with monotonous cnt stack, then use to maintain last

-1 for that because every time when the pair joined a R LR L = R is certain to satisfy certain minimum conditions so that is the minimum value is -1 so the answer must satisfy -1 meaning there is no build any initialization value can be 

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=1e5+10;

int minn[N<<2],t[N<<2],n,m,col[N<<2],a[N];
ll ans;
void up(int pos)
{
    if(minn[pos<<1]==minn[pos<<1|1])
    minn[pos]=minn[pos<<1],t[pos]=t[pos<<1]+t[pos<<1|1];
    else if(minn[pos<<1]<minn[pos<<1|1])
    minn[pos]=minn[pos<<1],t[pos]=t[pos<<1];
    else minn[pos]=minn[pos<<1|1],t[pos]=t[pos<<1|1];
}
void down(int pos)
{
    if(!col[pos])return;
    col[pos<<1]+=col[pos];
    col[pos<<1|1]+=col[pos];
    minn[pos<<1]+=col[pos];
    minn[pos<<1|1]+=col[pos];
    col[pos]=0;
}
void build(int l,int r,int pos)
{   
    col[pos]=0;
    if(l==r){minn[pos]=0;t[pos]=1;return ;}
    int m=(l+r)>>1;build(l,m,pos<<1);build(m+1,r,pos<<1|1);
    up(pos);
}
void UPsum(int L,int R,int v,int l,int r,int pos)
{
    if(L<=l&&r<=R){col[pos]+=v;minn[pos]+=v;return ;}
    int m=(l+r)>>1;down(pos);
    if(L<=m)UPsum(L,R,v,l,m,pos<<1);
    if(R>m)UPsum(L,R,v,m+1,r,pos<<1|1);
    up(pos);
}
stack<int>ma,mi;map<int,int>mp;
int main()
{
    int cas;cin>>cas;int kase=0;
    while(cas--)
    {   
        mp.clear();
        while(!ma.empty())ma.pop();
        while(!mi.empty())mi.pop();
        ans=0;
        scanf("%d",&n);
        build(1,n,1);
        rep(i,1,n)scanf("%d",&a[i]);
        int pre;
        rep(i,1,n)
        {
            while(!ma.empty())//维护单调递减
            {
                int k=ma.top();
                if(a[k]>=a[i])break;

                ma.pop();
                if(ma.empty())pre=1;
                else pre=ma.top()+1;
                UPsum(pre,k,-a[k],1,n,1);
            }
            if(ma.empty())pre=1;
            else pre=ma.top()+1;
            ma.push(i);
            UPsum(pre,i,a[i],1,n,1);

            while(!mi.empty())
            {
                int k=mi.top();
                if(a[k]<=a[i])break;
                mi.pop();
                if(mi.empty())pre=1;
                else pre=mi.top()+1;
                UPsum(pre,k,a[k],1,n,1);
            }
            if(mi.empty())pre=1;
            else pre=mi.top()+1;
            mi.push(i);
            UPsum(pre,i,-a[i],1,n,1);

            if(!mp[a[i]])pre=1;
            else pre=mp[a[i]]+1;
            UPsum(pre,i,-1,1,n,1);
            mp[a[i]]=i;
            ans+=t[1];
        }
        printf("Case #%d: %lld\n",++kase,ans);
    }
}
View Code

 

Guess you like

Origin www.cnblogs.com/bxd123/p/11440564.html