jzoj6374。NOIP2019アナログ[2019年10月4日]ウォード[生と死の領域]

ここに画像を挿入説明
ここに画像を挿入説明
ここに画像を挿入説明

大会

これは、この質問にはほぼ2時間の授業を取った。
欲の法則を発見し、70ポイントの水が考えることができます。
しかしグースディスカバリデータは、高精度がしたいためには大きすぎると思われるのですか?
心理崩壊、そして最終的にさえ、彼は20ポイントを取得できませんでした。
しかし、彼女は精度がヒットしない、小さな自然を発見しました。
あまりにも料理。

問題の解決策

まず、柿を描きます。
答えは\(\ sum_ {i = L
} ^ R a_iを* 2 ^ {K_I} \) kが配列され制御され得ます。
貪欲考えてみましょう。
私たちは、正の数のために、もちろん、より大きなそのk値ことを願っていことがわかりました。
負の数のために、そのk値の小さい所望のコース。
次いで、各負のために、K 1の最小値(0が最初の位置である)
と、正のインターバルの期間をインクリメントします。

もちろん、これは間違ってドロップです。なぜ?私たちは2で、いくつかの正の範囲を配置し、負の数の前に組み込まれ、その答えは大きくなることがあります。
これは、マージされた後、状況がそれを発生することがありますk個のアレイブロックに分割され、各ブロックの先頭には、1(最初のブロックの先頭0)以降の増分です。

だから我々は、合併がマージされていない現在のブロックの終わりに負であれば、注文番号、その後、現在のデジタル王Qianmianの合併に参加することを残しました。
しかし、ああ死ぬつもりの値は?方法は?私たちは、負の数があまりにも長い間4E9よりも大きな倍の正の数は王Qianmian狂気をマージできるよう、最小-2e9あり、特に小さくないことがわかりました。
だから我々は、マルチ値は分を取ることができ、スタックブロック4E9の現在の値を示して記録します。

彼は70ポイント、良い結果を得ました。

100ポイントのためにそれ?
私たちは、もの上記と同様の操作を行い、数字を追加することで、その後、ソートのエンドポイントを持っているの問い合わせに応じて、オフラインに尋ねます。
次に、左端点は、それが直接(ナンセンス)をカウントすることができない、1ない求めので
、この点は、2つの部分に分割片に残さなければなりません。
この1は、右部分を見つけることができます。

そこで質問です:スプリットの右部分に第二部では、それをマージされないのだろうか?
答えは:なし。
私たちは、ブロックの左端がゼロより小さい点(そうやってのプロセスにマージされていた)の右側のブロックの値がわかりますので、我々は値が0未満であることを知っているが連結されていない、それがマージされません。

次に、メンテナンスブロックまたはセグメントツリーに互いに素なセットを使用。

標準プロセス

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cctype>
using namespace std;
const int maxn=500010;
const long long mo=1000000007;

struct node{
    long long le,ri,kk,gg,lazy;
};

int n,m,l[maxn],r[maxn],gs,now;
long long a[maxn],b[maxn],c[maxn],mi[maxn],sum[maxn],jl,jr,jk,jg;
long long le[maxn],ri[maxn],k[maxn],zs[maxn],aa[maxn],qsum[maxn],col[maxn],id[maxn],wz[maxn],jll[maxn],qh[maxn],zd[maxn];
node tree[4*maxn];

void down_lazy(int x)
{
    if (tree[x].lazy==1)
    {
        tree[x*2].le=tree[x].le;
        tree[x*2+1].le=tree[x].le;
        tree[x*2].ri=tree[x].ri;
        tree[x*2+1].ri=tree[x].ri;
        tree[x*2].kk=tree[x].kk;
        tree[x*2+1].kk=tree[x].kk;
        tree[x*2].lazy=tree[x].lazy;
        tree[x*2+1].lazy=tree[x].lazy;
        tree[x*2].gg=tree[x].gg;
        tree[x*2+1].gg=tree[x].gg;
        tree[x].lazy=0;
    }
}

void change(int x,int l,int r,int st,int en,int le,int ri,int kk,int g)
{
    if (l==st && r==en)
    {
        tree[x].le=le;
        tree[x].ri=ri;
        tree[x].kk=kk;
        tree[x].gg=g;
        tree[x].lazy=1;
    }
    else
    {
        down_lazy(x);
        int mid=(l+r)/2;
        if (mid>=en) change(x*2,l,mid,st,en,le,ri,kk,g);
        else if (mid<st) change(x*2+1,mid+1,r,st,en,le,ri,kk,g);
        else
        {
            change(x*2,l,mid,st,mid,le,ri,kk,g);
            change(x*2+1,mid+1,r,mid+1,en,le,ri,kk,g);
        }
    }
}

void find(int x,int l,int r,int st)
{
    if (l==r)
    {
        jl=tree[x].le;
        jr=tree[x].ri;
        jk=tree[x].kk;
        jg=tree[x].gg;
    }
    else
    {
        down_lazy(x);
        int mid=(l+r)/2;
        if (mid>=st) find(x*2,l,mid,st);
        else find(x*2+1,mid+1,r,st);
    }
}

long long min(long long a,long long b)
{
    if (a<b) return a;return b;
}

void qsort(int ll,int rr)
{
    int i=ll;int j=rr;
    long long m=r[(i+j)/2];
    while (i<=j)
    {
        while (r[i]<m) i++;
        while (r[j]>m) j--;
        if (i<=j)
        {
            swap(r[i],r[j]);
            swap(l[i],l[j]);
            swap(wz[i],wz[j]);
            i++;j--;
        }
    }
    if (ll<j) qsort(ll,j);
    if (rr>i) qsort(i,rr); 
}

long long qsm(long long a,long long b)
{
    long long t=1;
    long long y=a;
    while (b>0)
    {
        if ((b&1)==1) t=t*y%mo;
        y=y*y%mo;
        b/=2;
    }
    return t;
}

int main()
{
//  freopen("data.in","r",stdin);
//  freopen("data.out","w",stdout);
    freopen("standard.in","r",stdin);
    freopen("standard.out","w",stdout);
    mi[0]=1;
    for (int i=1;i<=500000;i++)
    {
        mi[i]=mi[i-1]*2%mo;
    }
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%l64d",&a[i]);
        zd[i]=(zd[i-1]+a[i]*mi[i]%mo)%mo;
    }
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d",&l[i],&r[i]);
    }
    for (int i=1;i<=m;i++)
    {
        wz[i]=i;
    }
    qsort(1,m);
    k[1]=0;le[1]=1;ri[1]=1;zs[1]=a[1];gs=1;aa[1]=a[1];qh[1]=(a[1]+mo)%mo;
    change(1,1,n,le[gs],ri[gs],le[gs],ri[gs],k[gs],gs);
    int op=1;
    while (r[op]==1)
    {
        jll[wz[op]]=(qh[1]+mo)%mo;
        op++;
    }
    for (int j=2;j<=n;j++)
    {
        long long zss=a[j]*2;long long aaa=a[j]*2%mo;
        int kk=1;
        if (a[j]>0)
        {
            while (gs>0 && zs[gs]+zss*mi[k[gs]]>0)
            {
                zss=min(5000000000,zs[gs]+zss*mi[k[gs]]);
                aaa=(aa[gs]+aaa*mi[k[gs]]%mo+mo)%mo;
                kk=kk+k[gs];
                gs--;
            }
            if (gs==0)
            {
                gs++;
            }
            else
            {
                zss=min(5000000000,zs[gs]+zss*mi[k[gs]]);
                aaa=(aa[gs]+aaa*mi[k[gs]]%mo+mo)%mo;
                kk=k[gs]+kk;
            }
            ri[gs]=j;
            k[gs]=kk;
            zs[gs]=zss;
            aa[gs]=aaa;
            qh[gs]=(qh[gs-1]+aaa+mo)%mo;
        }
        else
        {
            gs++;
            le[gs]=j;
            ri[gs]=j;
            zs[gs]=zss;
            k[gs]=kk;
            aa[gs]=aaa;
            qh[gs]=(qh[gs-1]+aaa+mo)%mo;
        }
        change(1,1,n,le[gs],ri[gs],le[gs],ri[gs],k[gs],gs);
        while (op<=m && j==r[op])
        {
            if (l[op]==r[op])
            {
                jll[wz[op]]=a[l[op]];
                op++;
            }
            else
            {
                jr=0;jl=0;jk=0;jg=0;
                if (l[op]>1)
                {
                    find(1,1,n,l[op]-1);
                    jll[wz[op]]=(qh[gs]-qh[jg]+mo)%mo;
                    int opt=0;
                    if (jk==jr-jl+1) opt=1;
                    jll[wz[op]]=(jll[wz[op]]+(zd[jr]-zd[l[op]-1]+mo)%mo*qsm(mi[jr-(jk-(l[op]-jl))+opt],mo-2)%mo)%mo;
                    
                    int pd=jl;
                    jr=0;jl=0;jk=0;jg=0;
                    find(1,1,n,l[op]);
                    if (jl!=pd)
                    {
                        jll[wz[op]]=(jll[wz[op]]-(zd[jr]-zd[jl-1]+mo)%mo*qsm(mi[jr-jk+1],mo-2)%mo)%mo;
                    }
                    op++;
                }
                else
                {
                    jll[wz[op]]=(qh[gs]+mo)%mo;
                    op++;
                }
            }
        }
    }
    for (int i=1;i<=m;i++)
    {
        printf("%l64d\n",(jll[i]+mo)%mo);
    }
}

おすすめ

転載: www.cnblogs.com/RainbowCrown/p/11628120.html