bzoj 4826: [Hnoi2017]影魔

将区间[L,R]和点对(i,j)看作平面上的点,则询问为矩形求和

建出笛卡尔树,对应找出贡献为p1或p2的点,p1类的点总数为$O(n)$,p2类的点可以分为$O(n)$组,每组对应一条水平或竖直线段

最后用扫描线统计一下答案

#include<cstdio>
#include<algorithm>
typedef long long i64;
const int N=200007;
#define G *++ptr
char buf[N*30],*ptr=buf-1;
int _(){
    int x=0,c=G;
    while(c<48)c=G;
    while(c>47)x=x*10+c-48,c=G;
    return x;
}
int n,m,p1,p2,a[N],ss[N],sp=0;
int ch[N][2],lr[N][2];
i64 as[N];

i64 kb[N][2],bit[N][2];
void kb_add(int w,i64 k,i64 b){
    for(;w<=n;w+=w&-w){
        kb[w][0]+=k;
        kb[w][1]+=b;
    }
}
void kb_sum(int w,i64&_k,i64&_b){
    i64 k=0,b=0;
    for(;w;w-=w&-w){
        k+=kb[w][0];
        b+=kb[w][1];
    }
    _k=k;_b=b;
}
void add(int w,i64 a){
    i64 b=a*(w-1);
    for(;w<=n;w+=w&-w){
        bit[w][0]+=a;
        bit[w][1]+=b;
    }
}
i64 sum(int w){
    i64 a=0,b=0,w0=w;
    for(;w;w-=w&-w){
        a+=bit[w][0];
        b+=bit[w][1];
    }
    return a*w0-b;
}

struct Q{
    int x,y,id;
    bool operator<(Q w)const{return x>w.x;}
    void work(){
        i64 k,b;
        kb_sum(y,k,b);
        as[id]=sum(y)+k*x+b;
    }
}qs[N];
struct E{
    int x,y,tp,y2;
    bool operator<(E w)const{return x>w.x;}
    void work(){
        if(tp==0){
            kb_add(y,0,p1-p2);
        }else if(tp==1){
            add(y,p2);
            add(y2+1,-p2);
        }else if(tp==2){
            kb_add(y,-p2,i64(1+x)*p2);
        }else{
            kb_add(y,p2,i64(-x-1)*p2);
        }
    }
}es[N*8];
int ep=0;
void dfs(int w){
    int lc=ch[w][0],rc=ch[w][1];
    lr[w][0]=lr[w][1]=w;
    if(lc){
        dfs(lc);
        lr[w][0]=lr[lc][0];
        es[ep++]=(E){lr[lc][1],w,2};
        es[ep++]=(E){lr[lc][0]-1,w,3};
    }
    if(rc){
        dfs(rc);
        lr[w][1]=lr[rc][1];
        es[ep++]=(E){w,lr[rc][0],1,lr[rc][1]};
    }
}
int main(){
    fread(buf,1,sizeof(buf),stdin)[buf]=0;
    n=_();m=_();p1=_();p2=_();
    for(int i=1;i<=n;++i)a[i]=_();
    for(int i=1;i<=n;++i){
        ch[ss[sp]][1]=i;
        while(sp&&a[ss[sp]]<a[i]){
            int w=ss[sp--];
            ch[w][1]=ch[i][0];
            ch[i][0]=w;
            ch[ss[sp]][1]=i;
        }
        ss[++sp]=i;
    }
    dfs(ch[0][1]);
    for(int w=1;w<=n;++w){
        for(int u=ch[w][0];u;u=ch[u][1])es[ep++]=(E){u,w,0};
        for(int u=ch[w][1];u;u=ch[u][0])es[ep++]=(E){w,u,0};
    }
    std::sort(es,es+ep);
    for(int i=0;i<m;++i){
        qs[i].x=_();
        qs[i].y=_();
        qs[i].id=i;
    }
    std::sort(qs,qs+m);
    for(int i=0,j=0;i<m;++i){
        while(j<ep&&es[j].x>=qs[i].x)es[j++].work();
        qs[i].work();
    }
    for(int i=0;i<m;++i)printf("%lld
",as[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/ccz181078/p/6727641.html