1 条题解

  • 0
    @ 2025-8-24 23:01:00

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Petit_Souris
    鼓励的话语 无论多少次我都会说给你听 | 你在名为弱小的深渊 究竟看见过什么 | 天空中出现了一种罕见的天文现象

    搬运于2025-08-24 23:01:00,当前版本为作者最后更新于2024-08-03 14:59:38,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题面已经告诉我们了:ii 处的积水为 HhiH-h_i,其中 HHii 左侧的最大值和 ii 右侧的最大值中的较小值。我们分成 H\sum Hhi\sum h_i 两部分计算。

    hi\sum h_i 是好计算的,这就是 2n1(ai+bi)2^{n-1}\sum (a_i+b_i)。(你可以考虑计算每个位置的贡献)

    对于 H\sum H,我们不妨采用这样一种方式计算:把 HH 拆成 X=1[HX]\sum\limits_{X=1}^{\infty}[H\ge X],也就是枚举 XX,计算每个位置 HXH\ge X 的方案数之和。

    我们对 XX 从大到小做扫描线,将 X\ge X 的设为 11X\le X 的设为 00。这样每个位置就有三种状态:ai,bia_i,b_i 中恰好有 0/1/20/1/211。我们现在要给每个位置选一个 aia_ibib_i,并统计有多少位置 ii 满足 [1,i][1,i][i,n][i,n] 中都至少有一个 11,对这样的数量求和。

    我们分类讨论一下:当存在至少一个位置有 2211 的时候,设最左边的为 LL,最右边的为 RR,那么 [L,R][L,R] 中的位置任意填都可以满足,[1,L1][1,L-1] 中的只需要满足前缀中有 11[R+1,n][R+1,n] 中的只需要满足后缀中有 11

    假设正在统计 x[1,L1]x\in [1,L-1] 的贡献,设 [1,x1][1,x-1] 中有 pp 个位置有 1111,那么方案数为 (2p1)2xp=2x2xp(2^p-1)2^{x-p}=2^x-2^{x-p}。前面的这个贡献是固定的,后面这个贡献每当 xx 前面出现 11 的时候就会除以 22,可以用一个线段树维护,当扫描线将某些 00 修改成 11 的时候做一个后缀乘。[R+1,n][R+1,n] 的贡献同理。

    当不存在位置有 2211 的时候,设 xx 前面有 cLcL11,右边有 cRcR11,那么贡献为 (2cL1)(2cR1)2ncLcR(2^{cL}-1)(2^{cR}-1)2^{n-cL-cR},后面这个是个定值(扫到目前的 XX 对于所有 xx 来说 cL+cRcL+cR 都相等),前面的拆开后也可以类似上面一部分用两棵线段树维护。

    但是发现如果当前位置是 11,这个贡献是有问题的,因为自己选了 11 就同时满足了前缀和后缀,稍微分类讨论一下就可以了。

    总时间复杂度 O(nlogn)\mathcal O(n\log n)

    #include<bits/stdc++.h>
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    #define pii pair<ll,ll>
    #define rep(i,a,b) for(ll i=(a);i<=(b);++i)
    #define per(i,a,b) for(ll i=(a);i>=(b);--i)
    using namespace std;
    ll read(){
    	ll x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    void write(ll x){
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    }
    const ll N=5e5+9,Mod=1e9+7,inv2=(Mod+1)/2;
    ll n,a[N],b[N],L,R,cnt[N],tmp[N<<1],k,pw2[N],ta[N],tb[N],pre[N],bin[N],pre2[N];
    ll pw(ll x,ll p){
        ll res=1;
        while(p){
            if(p&1)res=res*x%Mod;
            x=x*x%Mod,p>>=1;
        }
        return res;
    }
    struct Tree{
        ll tr[N<<2],tag[N<<2];
        void Pushup(ll x){
            tr[x]=(tr[x<<1]+tr[x<<1|1])%Mod;
        }
        void Build(ll x,ll l,ll r,ll v){
            tag[x]=1;
            if(l==r){
                tr[x]=v;
                return ;
            }
            ll mid=(l+r)>>1;
            Build(x<<1,l,mid,v);
            Build(x<<1|1,mid+1,r,v);
            Pushup(x);
        }
        void Pushtag(ll x,ll v){
            tr[x]=tr[x]*v%Mod;
            tag[x]=tag[x]*v%Mod;
        }
        void Pushdown(ll x){
            if(tag[x]==1)return ;
            Pushtag(x<<1,tag[x]);
            Pushtag(x<<1|1,tag[x]);
            tag[x]=1;
        }
        void Upd(ll x,ll l,ll r,ll ql,ll qr,ll v){
            if(ql>qr)return ;
            if(l>qr||r<ql)return ;
            if(ql<=l&&r<=qr){
                Pushtag(x,v);
                return ;
            }
            ll mid=(l+r)>>1;
            Pushdown(x);
            Upd(x<<1,l,mid,ql,qr,v);
            Upd(x<<1|1,mid+1,r,ql,qr,v);
            Pushup(x);
        }
        void Cov(ll x,ll l,ll r,ll u,ll v){
            if(l>u||r<u)return ;
            if(l==r){
                tr[x]=v;
                return ;
            }
            ll mid=(l+r)>>1;
            Pushdown(x);
            Cov(x<<1,l,mid,u,v);
            Cov(x<<1|1,mid+1,r,u,v);
            Pushup(x);
        }
        ll Query(ll x,ll l,ll r,ll ql,ll qr){
            if(l>qr||r<ql||ql>qr)return 0;
            if(ql<=l&&r<=qr)return tr[x];
            ll mid=(l+r)>>1;
            Pushdown(x);
            return (Query(x<<1,l,mid,ql,qr)+Query(x<<1|1,mid+1,r,ql,qr))%Mod;
        }
    }T1,T2;
    vector<ll>vec[N<<1];
    bool Med;
    int main(){
        // freopen("wall.in","r",stdin);
        // freopen("wall.out","w",stdout);
        n=read();
        rep(i,1,n)a[i]=read();
        rep(i,1,n)b[i]=read();
        rep(i,1,n)tmp[i]=a[i];
        rep(i,1,n)tmp[i+n]=b[i];
        pw2[0]=1;
        rep(i,1,n)pw2[i]=pw2[i-1]*2%Mod;
        sort(tmp+1,tmp+(n<<1)+1);
        k=unique(tmp+1,tmp+(n<<1)+1)-tmp-1;
        rep(i,1,n){
            ta[i]=lower_bound(tmp+1,tmp+k+1,a[i])-tmp;
            tb[i]=lower_bound(tmp+1,tmp+k+1,b[i])-tmp;
        }
        T1.Build(1,1,n,pw2[n]),T2.Build(1,1,n,pw2[n]);
        rep(i,1,n){
            vec[ta[i]].push_back(i);
            vec[tb[i]].push_back(i);
        }
        rep(i,0,n-1)pre[i]=((pw2[n]+pw2[n-i])%Mod*(i+1)%Mod-2*pw2[n-i]%Mod*(pw2[i+1]-1)%Mod+Mod)%Mod;
        rep(i,0,n-1)pre2[i]=((pw2[n]+pw2[n-i-1])%Mod*(i+1)%Mod-2*pw2[n-i]%Mod*(pw2[i+1]-1)%Mod+Mod)%Mod;
        ll ans=0,c1=0;
        per(i,k,1){
            for(ll x:vec[i]){
                bin[x]++;
                if(bin[x]==2){
                    if(!L){
                        L=R=x;
                        T1.Build(1,1,n,pw2[n]);
                        T2.Build(1,1,n,pw2[n]);
                        rep(j,1,L){
                            if(bin[j]==1)T1.Upd(1,1,n,j,L,inv2);
                        }
                        rep(j,R+1,n){
                            if(bin[j]==1)T2.Upd(1,1,n,R,j,inv2);
                        }
                    }
                    else{
                        L=min(L,x);
                        R=max(R,x);
                    }
                }
                else {
                    c1++;
                    if(!L){
                        T1.Upd(1,1,n,x+1,n,inv2);
                        T2.Upd(1,1,n,1,x-1,inv2);
                    }
                    else {
                        if(x<=L)T1.Upd(1,1,n,x,L,inv2);
                        if(x>=R)T2.Upd(1,1,n,R,x,inv2);
                    }
                }
            }
            ll len=(i==1?tmp[i]:tmp[i]-tmp[i-1])%Mod;
            // cout<<"current "<<len<<" "<<L<<" "<<R<<endl;
            if(!L){
                ll coef=((pw2[n]+pw2[n-c1]+Mod)*n%Mod-T1.tr[1]-T2.tr[1]+Mod*2)%Mod;
                ll qd=pre[c1-1],nqd=pre2[c1-1];
                coef=(coef-nqd+qd*inv2%Mod+c1*pw2[n-1]%Mod+Mod)%Mod;
                // cout<<coef<<endl;
                ans=(ans+coef*len)%Mod;
            }
            else {
                ll coef=(pw2[n]*n%Mod-T1.Query(1,1,n,1,L-1)-T2.Query(1,1,n,R+1,n)+Mod*2)%Mod;
                // cout<<coef<<endl;
                ans=(ans+coef*len)%Mod;
            }
        }
        rep(i,1,n)ans=(ans-pw2[n-1]*(a[i]+b[i])%Mod+Mod)%Mod;
        write(ans);
    	return 0;
    }
    
    • 1

    信息

    ID
    10530
    时间
    4000ms
    内存
    512MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者