[Loj6092] [エール]訓練2017 1日目市場(セグメントツリー)

1,3,4は通常の動作を操作している、私が話すことはありません。

その後、我々は間隔部門に対処する方法を検討してください。

数を考える〜第容易\(X- \)を除く少なくとも一度に加えて、\(2 \) それ以外のまでである\(log_2(X)\)倍になる(0 \または\ 1 \)を\します

しかし、それはこのようなものを行うことができない、間隔の添加があるでしょう。

だから我々は、プロパティに気づきました:

もし:

\ [X- \ lfloor \ FRAC {X} {D} \ rfloor = Z- \ lfloor FRAC {Z}、{D} \ \ rfloor \]

そして、すべてのためにそこにある\(Y \)であれば、\(X \ Y leqslant \ leqslant Z \) その後、:

\ [X- \ lfloor FRAC {X} \ {D} \ rfloor = Y- \ lfloor \ FRAC {Y}、{D} \ rfloor = Z- \ lfloor FRAC {Z}、{D} \ \ rfloor \]

証明:

もし\(X \ Y leqslant \ leqslant Z \) その後、

\ [\ lfloor \ FRAC {X} {D} \ rfloor \ leqslant \ lfloor \ FRAC {Y}、{D} \ rfloor \ leqslant \ lfloor \ FRAC {Z}、{D} \ rfloor \]\ [\ lfloor \ FRAC {Y}、{D} \ rfloor- \ lfloor FRAC {X} {D} \ \ rfloor \ leqslant YX \]

明らか

キーダウンシフト:

\ [X- \ lfloor FRAC {X} {D} \ rfloor \ leqslant Y- \ lfloor \ FRAC {Y}、{D} \ \ rfloor \]

同様にご利用いただけます:

\ [Y- \ lfloor FRAC {Y}、{D} \ \ rfloor \ leqslant Z- \ lfloor \ FRAC {Z}、{D} \ rfloor \]

したがって:

\ [X- \ lfloor FRAC {X} {D} \ rfloor \ leqslant Y- \ lfloor \ FRAC {Y}、{D} \ \ rfloor \ leqslant Z- \ lfloor \ FRAC {Z}、{D} \ rfloor \]

だから、とき

\ [X- \ lfloor \ FRAC {X} {D} \ rfloor = Z- \ lfloor FRAC {Z}、{D} \ \ rfloor \]

場合は、すべてのために\(X \ Y leqslant \ leqslant Z \) 満たされています:

\ [X- \ lfloor FRAC {X} \ {D} \ rfloor = Y- \ lfloor \ FRAC {Y}、{D} \ rfloor = Z- \ lfloor FRAC {Z}、{D} \ \ rfloor \]

証明されました。

ナンセンスの束を言うので、単語の大部分を感じる......

だから、毎回私たちはどのような場合には、この区間の決定\([L、R] \ ) のを:

\ [minn- \ lfloor FRAC \ {ミネソタ州} {D} \ rfloor = maxn- \ lfloor \ FRAC {MAXN} {D} \ rfloor \]

存在しなければならないので\(ミネソタ州\ leqslant a_l、A_ {L + 1}、...、A_R \ leqslant MAXN \)

だから、そこになければなりません

\ [a_l- \ lfloor \ FRAC {a_l} {D} \ rfloor = A_ {L + 1} - \ lfloor \ FRAC {A_ {L + 1}}、{D} \ rfloor = ... = a_r- \ lfloor \ FRAC {A_R} {D} \ rfloor \]

あらゆる数の\(a_iを\)、\ (a_i- \ lfloor \ FRAC} {D} {a_iを\ rfloor \)であり、\は(a_iを\)になる\(\ lfloor \ FRAC {a_iを } {D} \ rfloor \)限り、数を削減する必要がある)\(a_iを\減算\(a_i- \ lfloor \ FRAC} {D} {a_iを\ rfloor \) 分割を達成することができます。

各数がこの値を減算する必要がありますので、だから、引き算の範囲です。

コードのこのセクションので:

void update2(int k,int l,int r,int ql,int qr,ll val)
{
    int x=floor(1.0*minn[k]/val)-minn[k];
    int y=floor(1.0*maxn[k]/val)-maxn[k];
    if(ql<=l&&r<=qr&&x==y)
    {
        sum[k]+=x*(r-l+1);//区间加(减)
        minn[k]+=x;
        maxn[k]+=x;
        lazy[k]+=x;
        return;
    }
    int mid=(l+r)>>1;
    down(k,l,r,mid);
    if(ql<=mid)update2(k<<1,l,mid,ql,qr,val);
    if(qr>mid)update2(k<<1|1,mid+1,r,ql,qr,val);
    up(k);
}

時間の複雑さ:\(O(Qの\ログ(N-)\ログ(V))\)

私は許可しません......

次のようにすべてのコードは次のとおりです。

#include<bits/stdc++.h>

#define N 100010
#define ll long long
#define LNF 0x7fffffffffffffff

using namespace std;

int n,m,a[N];
ll sum[N<<2],minn[N<<2],maxn[N<<2],lazy[N<<2];

void downn(int k,int l,int r,ll val)
{
    sum[k]+=val*(r-l+1);
    minn[k]+=val;
    maxn[k]+=val;
    lazy[k]+=val;
}

void down(int k,int l,int r,int mid)
{
    if(lazy[k])
    {
        downn(k<<1,l,mid,lazy[k]);
        downn(k<<1|1,mid+1,r,lazy[k]);
        lazy[k]=0;
    }
}

void up(int k)
{
    sum[k]=sum[k<<1]+sum[k<<1|1];
    minn[k]=min(minn[k<<1],minn[k<<1|1]);
    maxn[k]=max(maxn[k<<1],maxn[k<<1|1]);
}

void build(int k,int l,int r)
{
    if(l==r)
    {
        scanf("%lld",&sum[k]);
        maxn[k]=minn[k]=sum[k];
        return;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    up(k);
}

void update1(int k,int l,int r,int ql,int qr,ll val)
{
    if(ql<=l&&r<=qr)
    {
        downn(k,l,r,val);
        return;
    }
    int mid=(l+r)>>1;
    down(k,l,r,mid);
    if(ql<=mid)update1(k<<1,l,mid,ql,qr,val);
    if(qr>mid)update1(k<<1|1,mid+1,r,ql,qr,val);
    up(k);
}

void update2(int k,int l,int r,int ql,int qr,ll val)
{
    if(ql<=l&&r<=qr&&floor(1.0*minn[k]/val)-minn[k]==floor(1.0*maxn[k]/val)-maxn[k])
    {
        ll tmp=floor(1.0*minn[k]/val)-minn[k];
        downn(k,l,r,tmp);
        return;
    }
    int mid=(l+r)>>1;
    down(k,l,r,mid);
    if(ql<=mid)update2(k<<1,l,mid,ql,qr,val);
    if(qr>mid)update2(k<<1|1,mid+1,r,ql,qr,val);
    up(k);
}

ll query1(int k,int l,int r,int ql,int qr)
{
    if(ql<=l&&r<=qr)
        return minn[k];
    int mid=(l+r)>>1;ll ans=LNF;
    down(k,l,r,mid);
    if(ql<=mid)ans=min(ans,query1(k<<1,l,mid,ql,qr));
    if(qr>mid)ans=min(ans,query1(k<<1|1,mid+1,r,ql,qr));
    return ans;
}

ll query2(int k,int l,int r,int ql,int qr)
{
    if(ql<=l&&r<=qr)
        return sum[k];
    int mid=(l+r)>>1;ll ans=0;
    down(k,l,r,mid);
    if(ql<=mid)ans+=query2(k<<1,l,mid,ql,qr);
    if(qr>mid)ans+=query2(k<<1|1,mid+1,r,ql,qr);
    return ans;
}

int main()
{
    scanf("%d%d",&n,&m);
    build(1,1,n);
    while(m--)
    {
        int opt,l,r;
        scanf("%d%d%d",&opt,&l,&r);
        l++,r++;
        if(opt==1)
        {
            ll val;
            scanf("%lld",&val);
            update1(1,1,n,l,r,val);
        }
        if(opt==2)
        {
            ll val;
            scanf("%lld",&val);
            update2(1,1,n,l,r,val);
        }
        if(opt==3)
            printf("%lld\n",query1(1,1,n,l,r));
        if(opt==4)
            printf("%lld\n",query2(1,1,n,l,r));
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/ez-lcw/p/11781256.html