zoukankan      html  css  js  c++  java
  • 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;  
    } 
    

      

  • 相关阅读:
    cf359D Pair of Numbers
    cf671B Robin Hood
    [暑假集训--数位dp]hdu5787 K-wolf Number
    [暑假集训--数位dp]UESTC250 windy数
    [暑假集训--数位dp]LightOj1205 Palindromic Numbers
    [暑假集训--数位dp]LightOJ1140 How Many Zeroes?
    [暑假集训--数位dp]LightOj1032 Fast Bit Calculations
    [暑假集训--数位dp]hdu5898 odd-even number
    [暑假集训--数位dp]cf55D Beautiful numbers
    [暑假集训--数位dp]hdu3709 Balanced Number
  • 原文地址:https://www.cnblogs.com/guangheli/p/12384298.html
Copyright © 2011-2022 走看看