[JZOJ6279] 2019年8月5日[グループA]はNOIP美しいシーケンスを高めます

タイトル

効果の対象に

あなたは、各区間の数や配置間隔を与え、その美しい配列を含む最小の間隔をお願いします。
いわゆる美しいシーケンス、配列の重みの並べ替えを来た後、連続することができます。


歴史上のものがたり

美しいシーケンスは、明らかに、この条件が満たされている:\(MX-Mn系= RL \)
長い時間のように正の解決策を考え出すと、水の法律を描くようになったしませんでした。
最初の\(N、Mの\の当量1000年 \) 暴力は、各セクションが美しい範囲であるか否かを判断し、行に対するそれらのサブインターバルに対する回答を更新することができます。
(実際には、そうである場合、2つのセグメントツリーを構築し\(ST \)構築し、最大と最小の範囲を維持するための添字によれば、テーブルが良いだろう);
構造に応じた重み、右端下部標準体重の範囲左端のメンテナンス。
オフラインでは、全てのパイルクエリに投げ込まれ、それぞれの抽出は、彼の最小間隔を行っています。最大値と最小値を調べ、その後、右の最大値と最小値の標準の間で最も一番左の下を特定の間隔を拡張されます。
今、組み合わせの両方への互いに素-回答セットの間隔は、直接使用前に処理した場合。この範囲が扱われている場合、2番目のキーワードとして左のポイントと範囲とすることができ、それは最初のキーワードのための時間の長さには確かです。
拡張範囲は再びヒープに投げ込ま。あなたが展開できない場合、それは答えを見つけることを意味します。
この方法は非常に良いことができます\(76 \)ポイント。


水道法

私は水法のYYT叔父を言及する必要があります。
ランダムに配置されているトピックこのような特性によれば、あまりにもあまりにも美しい配列することができない(しかし、問題は平面ではないが、データ、幾分信頼できないである。前記しました)。
だから、すべての美しいシーケンスが模索されます。
列挙左端ポイント\(Lの\)間隔からは、\([L、L + 1 ] \) 上記の方法の拡張を使用して、水を開始します。拡張子がポイントのままにされていない場合は、\(リットル\)の出口を(それはそれをアップして計算されているように)。それは美しいシーケンスのすべてを扱うことができるように。
バックには、2次元の半順序の問題です。


正解

問題の実践ソリューションを分割し、征服することです。それは何をするのか分からない......実際には、良い意味に見えます。(あまりにも簡単な問題への解決策)
タイトルナレーション時間複雑です\(O(n個の\ LG ^ 2 n)が\) です。
思想に基づいてWHHパーティション\(O(N \のLG ^ 3 N)\) アプローチ。右ここにちょうど約。
同じ分割統治。よると、\(MX \)\(MN \) それぞれ、左または右を実行するために、だけでなく、木の会長とに対処するために4例に分かれている彼の......

絶対に正の解がされてあり一緒に木を解析し学習している、......(WMYが%%%になります)
この質問は、テンプレートツリーああを一緒に分析されて......

私が考えるベッドで夜に、彼は練習のブロックを思い付きました。
列挙右点\(R&LTの\)満たすために、左点\(L + R&LT mx_l-mn_l = \)を式の左側に位置している(S_L \)を\します
前にも同様の問題を見て。単調に各2スタックを維持することができます\(mx_l \)\(mn_l \) およびメンテナンス\(S_L \)
式の両辺ので、私は同じであるので、ブロックをスコアリングするように。
各ブロックのためのオープンバレルが好きです。
クエリのために\([L、R&LT] \) 右端点は逆方向列挙を開始し、最初の発見(私は\)\は、現在間隔満足\([j、i]は\ ) を含む\([LをR] \) そして、範囲は(最小を取るために同じ権利ポイント範囲のより多くの)答えがあります。
なぜ?あった場合(Iは、I <\ 'が\) 間隔がある([I' \ J' \]) も含む\([L、R] \ ) よりも短い長さ(\ [I、J])\、次いで2つの断面は、\([J 'i]は \) も美しい順序でなければならないので、答えは\([J'、i]と \)この間隔。
二つの美しい配列はまた証拠がそれらを繰り返すことはしません、美しいシーケンスを支払わなければなりません。
次に、あなたがすることができます(O(nは\ sqrtのN \ )\) この質問の上にカードを。

その後、彼女は悲しい真実を発見:実際には、\(mx_l-mn_l \ GEQ RL \)
理由......それを言わない
、セグメントツリーのメンテナンス\(S_Lを\)見て、最小うまくセグメントバイナリツリーは、不等式の両側にほぼ等しく満足見つけたとき\(Lの\)
時間複雑\(O(N-LG)\ n-は\)、......多くを最適化し
、私はこれが本当の意味での正の解だと思います。分割統治アプローチは、それが木解析が一緒に、新しい知識されているかわからなかったし、完全に思考を行使するために使用されるツリー解析方法を一緒に勉強するために、この方法は適したものでなければならない......


コード

唯一の練習をブロック果たした......


using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define N 100010
#define maxK 400
inline int input(){
    char ch=getchar();
    while (ch<'0' || '9'<ch)
        ch=getchar();
    int x=0;
    do{
        x=x*10+ch-'0';
        ch=getchar();
    }
    while ('0'<=ch && ch<='9');
    return x;
}
int n,m;
int a[N];
int smn[N],tmn,smx[N],tmx;
struct Quest{
    int l,r,num;
} q[N];
int h[N],nh;
int ansl[N],ansr[N];
inline bool cmpq(const Quest &x,const Quest &y){return x.r<y.r;}
inline bool cmph(int son,int fa){return q[son].l<q[fa].l;}
int K,nb;
int bel[N],end[N];
int tag[N];
int s[N];
int bz[maxK],hav[maxK][N],lef[maxK][N];
inline bool pushdown(int x){
    if (!tag[x])
        return 0;
    for (int i=end[x-1]+1;i<=end[x];++i)
        s[i]+=tag[x];
    tag[x]=0;
    return 1;
}
inline void rebuild(int x){
    bz[x]++;
    for (int i=end[x-1]+1;i<=end[x];++i)
        if (s[i]<=n && hav[x][s[i]]!=bz[x]){
            hav[x][s[i]]=bz[x];
            lef[x][s[i]]=i;
        }
}
inline void change(int l,int r,int c){
    if (bel[l]==bel[r]){
        pushdown(bel[l]);
        for (int i=l;i<=r;++i)
            s[i]+=c;
        rebuild(bel[l]);
        return;
    }
    pushdown(bel[l]);
    for (int i=l;i<=end[bel[l]];++i)
        s[i]+=c;
    rebuild(bel[l]);
    pushdown(bel[r]);
    for (int i=end[bel[r]-1]+1;i<=r;++i)
        s[i]+=c;
    rebuild(bel[r]);
    for (int i=bel[l]+1;i<bel[r];++i)
        tag[i]+=c;
}
int main(){
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    n=input();
    for (int i=1;i<=n;++i)
        a[i]=input();
    K=sqrt(n);
    for (int i=1;i*K<=n;++i){
        ++nb;
        for (int j=(i-1)*K+1;j<=i*K;++j)
            bel[j]=nb;
        end[nb]=i*K;
    }
    if (n%K){
        ++nb;
        for (int i=n/K*K+1;i<=n;++i)
            bel[i]=nb;
        end[nb]=n;
    }
    for (int i=1;i<=nb;++i)
        rebuild(i);
    m=input();
    for (int i=1;i<=m;++i){
        q[i]={input(),input(),i};
        if (q[i].l==q[i].r)
            ansl[i]=ansr[i]=q[i].l;
    }
    sort(q+1,q+m+1,cmpq);
    smn[tmn=1]=smx[tmx=1]=1;
    change(1,1,1);
    for (int i=2,j=1;i<=n;++i){
        for (;j<=m && q[j].r<=i;++j)
            if (q[j].l<q[j].r){
                h[nh++]=j;
                push_heap(h,h+nh,cmph);
            }
        while (tmn && a[smn[tmn]]>a[i]){
            change(smn[tmn-1]+1,smn[tmn],a[smn[tmn]]-a[i]);
            tmn--;
        }
        smn[++tmn]=i;
        while (tmx && a[smx[tmx]]<a[i]){
            change(smx[tmx-1]+1,smx[tmx],-a[smx[tmx]]+a[i]);
            tmx--;
        }
        smx[++tmx]=i;
        change(i,i,i);
        if (!nh)
            continue;
        int k,mnl=1;
        for (k=1;k<=bel[i];++k)
            if (hav[k][i-tag[k]]==bz[k]){
                mnl=lef[k][i-tag[k]];
                break;
            }
        k=bel[i];
        while (nh && q[*h].l>=mnl){
            int t=*h;
            pop_heap(h,h+nh--,cmph);
            for (;k>=1;--k)
                if (hav[k][i-tag[k]]==bz[k] && lef[k][i-tag[k]]<=q[t].l)
                    break;
            if (pushdown(k))
                rebuild(k);
            for (int ii=min(q[t].l,end[k]);ii>end[k-1];--ii)
                if (s[ii]==i){
                    ansl[q[t].num]=ii;
                    ansr[q[t].num]=i;
                    break;
                }
        }
    }
    for (int i=1;i<=m;++i)
        printf("%d %d\n",ansl[i],ansr[i]);
    return 0;
}

概要

何度も不平等な関係に隠さ多くがあり、我々は慎重に探しにする必要があります。
その後、あなたは木を一緒に分析することを学ばなければなりません!

おすすめ

転載: www.cnblogs.com/jz-597/p/11329452.html