其他分享
首页 > 其他分享> > 【loj3059】【hnoi2019】序列

【loj3059】【hnoi2019】序列

作者:互联网

题目

给出一个长度为 \(n\) 的序列 \(A\) ;

你需要构造一个新的序列\(B\) ,满足:

题解

#include<bits/stdc++.h>
#define ll long long 
#define mod 998244353
using namespace std;
const int N=100010;
int n,m,ny[N],pl,pr,len[N],ansl[N],ansr[N],pre[N],ql,qr,ans[N];
struct query{
    int x,y,id;
    query(int _x=0,int _y=0,int _id=0):x(_x),y(_y),id(_id){};
    bool operator <(const query&A)const{return x<A.x;}
}Q[N];
struct data{
    ll x,y,z;
    data(ll _x=0,ll _y=0,ll _z=0):x(_x),y(_y),z(_z){};
    data operator +(const data&A)const{return data(x+A.x,y+A.y,z+A.z);}
    data operator -(const data&A)const{return data(x-A.x,y-A.y,z-A.z);}
    bool operator <=(const data&A)const{return y*A.x<=A.y*x;}
    bool operator >=(const data&A)const{return y*A.x>=A.y*x;}
}A[N],L[N],R[N],pR[N],sL[N],sR[N],psR[N],X,Y,Z;
data getL(int l,int r){return sL[r]-sL[l-1];}
data getR(int l,int r){return sR[r]-sR[l-1];}
int cal(data now){
    int x=now.x,y=now.y%mod,z=now.z%mod;
    int v=(ll)y*ny[x]%mod;
    return (z-(ll)v*y*2%mod+(ll)v*v%mod*x%mod+mod)%mod;
}
void lowerL(){
    int l=1,r=pl+1;
    while(l<r){
        int mid=(l+r+1)>>1;
        Z=Y+getL(mid,pl);
        if(Z<=L[mid-1])r=mid-1;
        else l=mid;
    }
    Z=Y+getL(ql=l,pl);
}
void lowerR(){
    int l=1,r=pr+1;
    while(l<r){
        int mid=(l+r+1)>>1;
        Y=X+getR(mid,pr);
        lowerL();
        if(Z>=R[mid-1])r=mid-1;
        else l=mid;
    }
    Y=X+getR(qr=r,pr);
    lowerL();
}
int main(){
//  freopen("sequence.in","r",stdin);
//  freopen("sequence.out","w",stdout);
    scanf("%d%d",&n,&m);ny[1]=1;
    for(int i=2;i<=n;++i){ny[i]=1ll*(mod-mod/i)*ny[mod%i]%mod;}
    for(int i=1;i<=n;++i){
        int x;scanf("%d",&x);
        A[i]=data(1,x,(ll)x*x%mod);
    }
    for(int i=1;i<=m;++i){
        int x,y;scanf("%d%d",&x,&y);
        Q[i]=query(x,y,i);
    }
    sort(Q+1,Q+m+1);
    L[0]=data(1,0,0);
    R[0]=data(1,1e9+1,0);
    for(int i=n;~i;--i){
        data now=A[i];
        while(now>=R[pr])now=now+R[pr--];
        len[i]=++pr;
        pR[i]=R[pr];R[pr]=now;
        psR[i]=sR[pr];sR[pr]=sR[pr-1]+now;
        pre[i]=ansr[pr];ansr[pr]=(ansr[pr-1]+cal(now))%mod;
    }
    ans[0]=ansr[pr];
    for(int i=1,tl=0,tr=1;i<=m;++i){
        while(tr<Q[i].x+1){
            R[pr]=pR[tr];
            sR[pr]=psR[tr];
            ansr[pr]=pre[tr];
            pr=len[++tr];
        }
        while(tl<Q[i].x-1){
            data now=A[++tl];
            while(now<=L[pl])now=L[pl--]+now;
            L[++pl]=now;
            sL[pl]=sL[pl-1]+now;
            ansl[pl]=(ansl[pl-1]+cal(now))%mod;
        }
        X=data(1,Q[i].y,(ll)Q[i].y*Q[i].y%mod);
        lowerR();
        ans[ Q[i].id ] = ((ll)ansl[ql-1] + ansr[qr-1] + cal(Z)) %mod;
    }
    for(int i=0;i<=m;++i)printf("%d\n",ans[i]);
    return 0;
}

标签:pr,now,int,loj3059,mid,序列,hnoi2019,引理,mod
来源: https://www.cnblogs.com/Paul-Guderian/p/10801584.html