[Explanations] Luogu P5294 [HNOI2019] sequence

Original title Portal

Meaning of the questions: to give you a length \ (n \) sequence \ (A \) , Always ask to modify one element (valid only for the current inquiry), and then you do not find a drop sequence \ (B \) , so that and the minimum squared difference between the two sequences corresponding to the position, and outputs the least squares and

Example Description observation, found a very interesting properties, \ (B \) the same number of digits exactly section (A \) \ in this figure Mean

Must form the optimal solution is divided into several segments, each segment: Then we Naka to guess \ (B_i \) that is to take where \ (A_i \) average, while ensuring \ (B \) orderliness ( this paper seems to have proved)

How to find the best \ (B \) ? We Ke monotonous to use the stack

Consider enumeration \ (I \) , the \ ([i, i] \ ) into monotone stack, the stack segment and then compare the average value and below a stack of the average interval. If the top of the stack smaller interval for the mean, is not satisfied does not fall nature, so we merge these two intervals, and then continue with a range below and then compare ......

How to merge the answer? We only need to maintain the number range maintenance elements, the elements and the interval, the interval the elements and to the square (the same as the variance of that title)

Next, consider how to modify. When we seek the optimal solution of the entire sequence, with the President of tree maintenance \ (A \) for each prefix monotonous stack \ (pre \) . Similarly, he ran forward from the back once, with the Chairman of the maintenance tree \ (A \) monotonous stack for each suffix \ (SUF \) .

We will assume that position \ (pos \) values modified into \ (Val \) . After setting modify the optimal solution \ (pos \) zone is located is \ ([L, R] \) , if we can quickly find \ (L, R \) we Ke fast answer.

Notice a monotonically stack of any prefix average value greater than the average number remove the remaining prefix, so \ (L \) of \ (pre [pos-1] \) in an interval \ (L \) or \ (POS \) , \ (R & lt \) is \ (suf [pos + 1] \) in an interval \ (R & lt \) or \ (POS \)

Binary \ (R & lt \) position, the Chairman tree \ (pre [pos-1] \) bipartite matching the determined \ (L \) , determines whether or not valid. Eventually find the minimum legal \ (R \) , calculated \ (L \) , in order to Ke out the answer

#include <bits/stdc++.h>
#define N 100005
#define ll long long
#define mod 998244353 
#define getchar nc
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
inline int Max(register int a,register int b)
{
    return a>b?a:b;
}
int n,m,pre[N],prelen[N],suf[N],suflen[N],tot;
pair<int,int> s[N];
ll inv[N];
struct node{
    ll x,y,z;
    node(){x=y=z=0;}
    node(register ll _x,register ll _y,register ll _z){x=_x,y=_y,z=_z;}
    inline ll cal()
    {
        return (z+mod-(y%mod)*(y%mod)%mod*inv[x]%mod)%mod;
    }
}sum[N];
inline node Init(register ll v)
{
    return node(1,v,v*v%mod);
}
inline node operator + (node a,node b){return (node){a.x+b.x,a.y+b.y,(a.z+b.z)%mod};}
inline node operator - (node a,node b){return (node){a.x-b.x,a.y-b.y,(a.z-b.z+mod)%mod};}
inline bool operator < (node a,node b){
    if(!a.x)
        return b.x;
    if(!b.x)
        return 0;
    return (double)a.y/a.x<(double)b.y/b.x;
}
inline node cal(register int l,register int r)
{
    if(!l&&!r)
        return node(0,0,0);
    return sum[r]-sum[l-1];
}
struct seg{
    int ls,rs,L,R,ans,Rp;
    inline void merge(register seg a,register seg b)
    {
        L=a.L;
        R=Max(a.R,b.R);
        ans=(a.ans+b.ans)%mod;
        Rp=a.Rp;
    }
}tr[N*80];
inline void modify(register int &x,register int l,register int r,register int pos,register int L,register int R)
{
    tr[++tot]=tr[x];
    x=tot;
    if(l==r)
        tr[x]=(seg){0,0,L,R,cal(L,R).cal(),R};
    else
    {
        int mid=l+r>>1;
        if(pos<=mid)
            modify(tr[x].ls,l,mid,pos,L,R);
        else
            modify(tr[x].rs,mid+1,r,pos,L,R);
        tr[x].merge(tr[tr[x].ls],tr[tr[x].rs]);
    }
}
inline int query_suf(register int x,register int l,register int r,register int pos)
{
    if(l==r)
        return tr[x].R;
    int mid=l+r>>1;
    if(pos<=mid)
        return query_suf(tr[x].ls,l,mid,pos);
    else
        return query_suf(tr[x].rs,mid+1,r,pos);
}
inline int query_pre(register int x,register int l,register int r,register int pos,register node &val)
{
    if(r<=pos)
    {
        node twh=cal(tr[x].L,tr[x].R),tlf=cal(tr[x].L,tr[x].Rp);
        if(!(tlf<val+twh))
        {
            val=val+twh;
            return 0;
        }
        if(l==r)
            return tr[x].R;
    }
    int mid=l+r>>1,res=0;
    if(pos>mid)
        res=query_pre(tr[x].rs,mid+1,r,pos,val);
    if(res)
        return res;
    return query_pre(tr[x].ls,l,mid,pos,val);
}
int main()
{
    n=read(),m=read();
    inv[1]=1;
    for(register int i=2;i<=n;++i)
        inv[i]=inv[mod%i]*(mod-mod/i)%mod;
    for(register int i=1;i<=n;++i)
        sum[i]=sum[i-1]+Init(read());
    for(register int i=1,top=0;i<=n;++i)
    {
        pre[i]=pre[i-1];
        int l=i;
        while(top&&!(cal(s[top].first,s[top].second)<cal(l,i)))
            modify(pre[i],1,n,top,0,0),l=s[top--].first;
        s[prelen[i]=++top]=make_pair(l,i);
        modify(pre[i],1,n,top,l,i);
    }
    for(register int i=n,top=0;i;--i)
    {
        suf[i]=suf[i+1];
        int r=i;
        while(top&&!(cal(i,r)<cal(s[top].first,s[top].second)))
            modify(suf[i],1,n,top,0,0),r=s[top--].second;
        s[suflen[i]=++top]=make_pair(i,r);
        modify(suf[i],1,n,top,i,r);
    }
    write(tr[pre[n]].ans),puts("");
    while(m--)
    {
        int x=read(),y=read();
        int l=0,r=suflen[x+1]-1,res=r+1;
        while(l<=r)
        {
            int mid=l+r>>1;
            int rp=mid?query_suf(suf[x+1],1,n,suflen[x+1]-mid+1):x;
            node val=Init(y)+cal(x+1,rp);
            int lp=x>1?query_pre(pre[x-1],1,n,prelen[x-1],val):1;
            if(val<cal(rp+1,query_suf(suf[x+1],1,n,suflen[x+1]-mid)))
                res=mid,r=mid-1;
            else
                l=mid+1;
        }
        int rp=res?query_suf(suf[x+1],1,n,suflen[x+1]-res+1):x;
        node val=Init(y)+cal(x+1,rp);
        int lp=x>1?query_pre(pre[x-1],1,n,prelen[x-1],val):1;
        write((val.cal()+tr[pre[lp]].ans+tr[suf[rp+1]].ans)%mod),puts("");
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/yzhang-rp-inf/p/10960923.html