CF2045E 做题记录

前言

在别的博客你看不见这个玩意的
函数这个东西很烦人,\(min\) 可以很短也可以很长,有很多种方式表达,大部分题目会固定一部分问题剩下的问题可以很容易求出,通常固定的那一部分可以通过转化函数的表达形式求出,这个方面很妙但是很少的人能做到这个事情
其实是一个好题别浪费了

题意

定义一个

\[\begin{equation} f({l,r})=\left\{ \begin{aligned} 0 \quad m1=m2\\ \min(m1,m2) \quad m1\ne m2\\ \end{aligned} \right . \end{equation} \]

其中 \(m1=\max\limits_{i=l}^r a_i,m2=\max\limits_{i=l}^r b_i\)
\(\sum\limits_{l=1}^{n}\sum\limits_{r=l}^rf(l,r)*2^{n-r+l-3}\)

做法

相信大家上面的东西一定推出来了,因为这个是题目很显然也是最简单的一部分,那么接下来的话就是前言说的解放这个函数,他是分段的,很让人恼怒,所以转化一下变成

\[m1+m2-[m1=\max(m1,m2)]*m1-[m2=\max(m1,m2)]*m2 \]

这个式子分开处理,\(m1,m2\) 可以通过对于每一个数找到左边第一个超过他的和右边第一个不小于他的,然后计算他对 \(m1\) 的贡献,同理,在他的控制范围内找到左边不超过他的 \(b\) 和右边不超过他的 \(b\) 然后同样计算贡献即可,计算的贡献通过推式子计算这里不做赘述,读者可以自己计算。

代码

//谁能写这么难看的代码 
//不想要用swap两个数组计算结果了,我使用的ST表找而非单调栈
#include<algorithm>
#include<iostream>
#include<cstring>
#include<climits>
#include<cmath>
#define ll long long

using namespace std;
const int N=1e5+9;
const ll mod=998244353;
ll sta[N][23],stb[N][23],lg[N];
ll kms[N],n,a[N],b[N];

inline ll querya(int l,int r){
    int tmp=lg[r-l+1];
    return max(sta[l][tmp],sta[r-(1<<tmp)+1][tmp]);
}
inline ll queryb(int l,int r){
    int tmp=lg[r-l+1];
    return max(stb[l][tmp],stb[r-(1<<tmp)+1][tmp]);
}

inline ll ksm(ll x,int y){
    if(x==2 && y<=n){
        if(y<0) return 0;
        return kms[y];
    }
    ll res=1;
    x%=mod;
    // cout<<x<<endl;
    while(y){
        // cout<<res<<' '<<y<<endl;
        if(y&1)res=res*x%mod;
        x=x*x%mod;y>>=1;
    }
    return res;
}
inline void init(){
    kms[0]=1;
    for(int i=1;i<=n;i++)
        kms[i]=kms[i-1]*2%mod;
    for(int i=2;i<=n;i++)
        lg[i]=lg[i>>1]+1;
    for(int i=1;i<=n;i++){
        sta[i][0]=a[i];
        stb[i][0]=b[i];
    }
    for(int i=1;i<=lg[n];i++){
        for(int j=1;j+(1<<i)-1<=n;j++){
            sta[j][i]=max(sta[j][i-1],sta[j+(1<<i-1)][i-1]);
            stb[j][i]=max(stb[j][i-1],stb[j+(1<<i-1)][i-1]);
        }
    }
}

int ltmax[N],rtmax[N];
ll ans;

inline ll mul(ll x,ll y){return x*y%mod;}
inline ll del(ll x,ll y){return ((x-y)%mod+mod)%mod;}
inline ll add(ll x,ll y){return (x+y)%mod;}

inline ll cost(int l,int r,int i){
    return del(ksm(2,n-i),ksm(2,n-r-1))*del(ksm(2,i-1),ksm(2,l-2))%mod;
}
inline void getcost1(){
    int lt,rt,mid;
    for(int i=1;i<=n;i++){
        lt=1,rt=i;
        ltmax[i]=i;
        while(lt<=rt){
            mid=lt+rt>>1;
            if(querya(mid,i)==a[i])
                rt=mid-1,ltmax[i]=mid;
            else lt=mid+1;
        }
        rtmax[i]=i;
        lt=i+1;rt=n;
        while(lt<=rt){
            mid=lt+rt>>1;
            if(querya(i+1,mid)<a[i])
                lt=mid+1,rtmax[i]=mid;
            else rt=mid-1;
        }
        // cout<<i<<' '<<ltmax[i]<<' '<<rtmax[i]<<endl;
        ans+=a[i]*cost(ltmax[i],rtmax[i],i);
        ans%=mod;
    }
    for(int i=1;i<=n;i++){
        lt=1,rt=i;
        ltmax[i]=i;
        while(lt<=rt){
            mid=lt+rt>>1;
            if(queryb(mid,i)==b[i])
                rt=mid-1,ltmax[i]=mid;
            else lt=mid+1;
        }
        rtmax[i]=i;
        lt=i+1;rt=n;
        while(lt<=rt){
            mid=lt+rt>>1;
            if(queryb(i+1,mid)<b[i])
                lt=mid+1,rtmax[i]=mid;
            else rt=mid-1;
        }
        ans+=b[i]*cost(ltmax[i],rtmax[i],i);
        ans%=mod;
    }
    return void();
}
//delete cost
inline void getcost2(){
    int lt,rt,mid;
    for(int i=1;i<=n;i++){
        if(a[i]<b[i]) continue;
        lt=1,rt=i;
        ltmax[i]=i;
        while(lt<=rt){
            mid=lt+rt>>1;
            if(querya(mid,i)==a[i] && queryb(mid,i)<=a[i])
                rt=mid-1,ltmax[i]=mid;
            else lt=mid+1;
        }
        rtmax[i]=i;
        lt=i+1;rt=n;
        while(lt<=rt){
            mid=lt+rt>>1;
            if(querya(i+1,mid)<a[i] && queryb(i,mid)<=a[i])
                lt=mid+1,rtmax[i]=mid;
            else rt=mid-1;
        }
        // cout<<"a "<<i<<' '<<ltmax[i]<<' '<<rtmax[i]<<' '<<a[i]*cost(ltmax[i],rtmax[i],i)<<endl;
        ans=del(ans,a[i]*cost(ltmax[i],rtmax[i],i));
    }
    for(int i=1;i<=n;i++){
        if(b[i]<a[i]) continue;
        lt=1,rt=i;
        ltmax[i]=i;
        while(lt<=rt){
            mid=lt+rt>>1;
            if(queryb(mid,i)==b[i] && querya(mid,i)<=b[i])
                rt=mid-1,ltmax[i]=mid;
            else lt=mid+1;
        }
        rtmax[i]=i;
        lt=i+1;rt=n;
        while(lt<=rt){
            mid=lt+rt>>1;
            if(queryb(i+1,mid)<b[i] && querya(i,mid)<=b[i])
                lt=mid+1,rtmax[i]=mid;
            else rt=mid-1;
        }
        // cout<<"b "<<i<<' '<<ltmax[i]<<' '<<rtmax[i]<<' '<<b[i]*cost(ltmax[i],rtmax[i],i)<<endl;
        ans=del(ans,b[i]*cost(ltmax[i],rtmax[i],i));
    }
    return void();
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
        cin>>b[i];
    init();
    getcost1();
    // cout<<ans<<endl;
    getcost2();
    cout<<ans*ksm(kms[n],mod-2)%mod;
    return 0;
}
posted @ 2025-10-28 16:38  zacharyzhongyq  阅读(8)  评论(0)    收藏  举报