bzoj4540 序列

做法同bzoj4262

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

int gint(){
    char c; int f=1;
    while(c=getchar(),c<48||c>57)
        if(c=='-')f=-1;
    int x=0;
    for(;c>47&&c<58;c=getchar()){
        x=x*10+c-48;
    }
    return x*f;
}

#define max_N 100005
#define mod 1000000000

int n,A[max_N];

void init(){
    int g1=1,g2=1;
    for(int i=1;i<=n;++i){
        g1=1ll*g1*1023%mod;
        g2=1ll*g2*1025%mod;
        A[i]=g1^g2;
    }
}

struct QY{
    int l,r,f,id,next;
    QY(int l=0,int r=0,int f=0,int id=0,int n=0):l(l),r(r),f(f),id(id),next(n){}
}Q[max_N<<1];

int t,head[max_N],tot;

inline void add_QY(int x,int l,int r,int f,int id){
    if(!x)return;
    Q[++tot]=QY(l,r,f,id,head[x]),head[x]=tot;
}

typedef long long ll;

struct data{
    ll v,s;
    int t;  
}T[max_N<<2];

inline data merge(const data&a,const data&b){
    data res;
    res.v=a.v+b.v;
    res.t=max(a.t,b.t);
    res.s=a.s+b.s+a.v*(res.t-a.t)+b.v*(res.t-b.t);
    return res;
}

struct tags{
    int a,tl,tr;
    ll s;
}tag[max_N<<2];

inline void modify(data&x,const tags&y,int len){
    x.s+=x.v*(y.tl-x.t)+y.s*len;
    x.v=1ll*y.a*len;
    x.t=y.tr;
}

inline void modify(tags&x,const tags&y){
    if(x.a==-1){x=y; return;}
    x.s+=1ll*x.a*(y.tl-x.tr)+y.s;
    x.a=y.a,x.tr=y.tr;
}

inline void putdown(int x,int l,int m,int r){
    if(tag[x].a==-1)return;
    modify(T[x<<1],tag[x],m-l+1);
    modify(tag[x<<1],tag[x]);
    modify(T[x<<1|1],tag[x],r-m);
    modify(tag[x<<1|1],tag[x]);
    tag[x].a=-1;
}

#define lch x<<1,l,m
#define rch x<<1|1,m+1,r

void modify(int x,int l,int r,int ll,int rr,int a,int t){
    if(ll<=l&&r<=rr){
        tags y;
        y.a=a,y.s=0,y.tl=y.tr=t;
        modify(T[x],y,r-l+1);
        modify(tag[x],y);
        return;
    }
    int m=(l+r)>>1;
    putdown(x,l,m,r);
    if(ll<=m)modify(lch,ll,rr,a,t);
    if(rr>m) modify(rch,ll,rr,a,t);
    T[x]=merge(T[x<<1],T[x<<1|1]);
}

data query(int x,int l,int r,int ll,int rr){
    if(l==ll&&r==rr)return T[x];
    int m=(l+r)>>1;
    putdown(x,l,m,r);
    if(rr<=m)return query(lch,ll,rr);
    if(ll>m) return query(rch,ll,rr);
    return merge(query(lch,ll,m),query(rch,m+1,rr));
}

int st[max_N],top;

ll ans[max_N];

void Tree_init(int x,int l,int r){
    T[x].v=T[x].s=T[x].t=0;
    tag[x].a=-1;
    if(l==r)return;
    int m=(l+r)>>1;
    Tree_init(x<<1,l,m);
    Tree_init(x<<1|1,m+1,r);
}

int main(){
//  freopen("input.txt","r",stdin);

    n=gint(),t=gint();
    for(int i=1;i<=n;++i)A[i]=gint();
    for(int i=1,l,r;i<=t;++i){
        l=gint(),r=gint();
        add_QY(l-1,l,r,-1,i),add_QY(r,l,r,1,i);
    }

    Tree_init(1,1,n);
    top=0;
    for(int i=1;i<=n;++i){
        while(top&&A[st[top]]>=A[i])--top;
        modify(1,1,n,st[top]+1,i,A[i],i);
        st[++top]=i;
        for(int j=head[i];j;j=Q[j].next){
            data tmp=query(1,1,n,Q[j].l,Q[j].r);
            ans[Q[j].id]+=(tmp.s+tmp.v*(i-tmp.t+1))*Q[j].f;
        }
    }

    for(int i=1;i<=t;++i){
        printf("%lld\n",ans[i]);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值