CF1117G Recursive Queries 单调栈+线段树

显然先用单调栈求出一个位置向左/右延申的最大长度(即这些区间中当前位置是最大值位置)   

然后我们发现我们可以离线,然后按照最大值位置依次添加线段,每次用线段树查一个区间和.   

然后我们想查满足最大值位置在 $[l,r]$ 之间,$[l,r]$ 内区间和.   

这个显然满足可减性(即最大值位置在 $[1,r]$ 减最大值位置在 $[1,l-1]$)   

code:  

#include <cstring> 
#include <algorithm> 
#include <string>   
#include <stack>    
#define N 1000006        
#define lson now<<1 
#define rson now<<1|1 
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;  
int n,Q;     
int A[N],lp[N],rp[N];  
stack<int>S;   
ll sum[N<<2],lazy[N<<2],ans[N];               
struct seq 
{   
    int l,r,mid;    
    seq(int l=0,int r=0,int mid=0):l(l),r(r),mid(mid){}     
}s[N];   
struct ask {
    int mid,l,r,id,opt;    
}as[N<<1];       
bool cmp(ask a,ask b) { return a.mid<b.mid; }            
void update(int l,int r,int now,int L,int R,int v) 
{       
    if(l>=L&&r<=R)     
    {
        lazy[now]+=v; 
        sum[now]+=(ll)(r-l+1)*v;    
        return;  
    }
    int mid=(l+r)>>1;    
    if(L<=mid)  
        update(l,mid,lson,L,R,v);   
    if(R>mid)  
        update(mid+1,r,rson,L,R,v);   
    sum[now]=sum[lson]+sum[rson]+(ll)(r-l+1)*lazy[now];   
}     
ll query(int l,int r,int now,int L,int R) 
{
    if(l>=L&&r<=R)   
        return sum[now];        
    int mid=(l+r)>>1;      
    ll re=(ll)(min(r,R)-max(l,L)+1)*lazy[now];   
    if(L<=mid)   
        re+=query(l,mid,lson,L,R);  
    if(R>mid)  
        re+=query(mid+1,r,rson,L,R);   
    return re;   
} 
int main() 
{ 
    // setIO("input"); 
    int i,j,tot=0;  
    scanf("%d%d",&n,&Q);    
    for(i=1;i<=n;++i) 
        scanf("%d",&A[i]);     
    A[0]=n+1,A[n+1]=n+1,S.push(0);   
    for(i=1;i<=n;++i) s[i].mid=i;  
    for(i=1;i<=n;++i)    
    {
        while(!S.empty()&&A[S.top()]<A[i]) 
            S.pop();    
        s[i].l=S.top()+1;    
        S.push(i);   
    }          
    while(!S.empty()) S.pop();   
    S.push(n+1);   
    for(i=n;i>=1;--i) 
    {
        while(!S.empty()&&A[S.top()]<A[i])  
            S.pop();  
        s[i].r=S.top()-1;  
        S.push(i);  
    }             
    for(i=1;i<=Q;++i) scanf("%d",&lp[i]);        
    for(i=1;i<=Q;++i) scanf("%d",&rp[i]);   
    for(i=1;i<=Q;++i) 
    {
        if(lp[i]-1) 
        {
            as[++tot].mid=lp[i]-1;            
            as[tot].l=lp[i];    
            as[tot].r=rp[i];   
            as[tot].id=i;   
            as[tot].opt=-1;  
        }   
        as[++tot].mid=rp[i];   
        as[tot].l=lp[i]; 
        as[tot].r=rp[i];  
        as[tot].id=i;  
        as[tot].opt=1;    
    }          
    sort(as+1,as+1+tot,cmp);   
    for(j=i=1;i<=tot;++i) 
    {    
        while(j<=as[i].mid&&j<=n) {
            update(1,n,1,s[j].l,s[j].r,1);   
            ++j;   
        }    
        ll cu=query(1,n,1,as[i].l,as[i].r);     
        ans[as[i].id]+=as[i].opt*cu;               
    }
    for(i=1;i<=Q;++i) 
    {      
        printf("%lld ",ans[i]);   
    }      
    return 0;  
} 

  

原文地址:https://www.cnblogs.com/guangheli/p/12384298.html