[JZOJ6355] [P] 100分の24アナログNOIP2019

タイトル

効果の対象に

すべてのために、配列を与える\(IN K \ [1、N-] \) 長シーク\(K \) 最大優先度の値の配列を、重み値\(A_1、A_2 + A_3 -... \午後a_k \)


歴史上のものがたり

この質問は明らかに権利をバックパックすることができます......
そう......それは直接、バックパック
、私は分裂を考えると征服ゲームが、双方一緒にはとても暴力的な直接の再生を、非常に遅いです。


正解

問題のセグメントツリーアプローチソリューションは、本当に理解していない見られています。
だから私は、分割統治の方法を言います。
最初の問題の結論に溶液がある:\(K \)サブシーケンスがなければならない(K-2 \)\挿入された2つのシーケンス番号。
挿入するために覚えているだけではなく、左右の延長に。
なぜ?反対の証拠を考慮していない場合、つまり、\(K-2 \)数列の複数を除去し、その後、複数の番号を挿入します。これは、効果的に対応する(KX \)\の状態にわたって転送、\(X> 2 \)
だから我々は唯一のことを証明する必要があります\(K-2 \)以前より良いよりも上で転送するための場所から転送します。
仮定\(K-3 \) 他の場合と同様)から転送します。
我々は、(K-2 \)\配列挿入配列の\(X \)\(Y \) 次いで、全配列がいくつかの部分に分割されている\(AxByC \)の正しい値(\ \のPMのxBを\ Y-PM + C \) 私たちが関係する必要はありません\(X \)をして、\(のy \)は、正または負である\(Bの\)は裏返しにするキャレットの後、元の貢献です)。
\(K-3 \)に挿入された配列\(X \)\(Y \)\(Z \) 我々は仮定\(X \)\(Y \)同じ挿入位置)に:\ (AxByDzE \)の右側の値、(\ \のPMのxBの\の午後
Y + D \のPM ZE \)は前半部分的に相殺比較、それはなる(C \)を\\(Dの\のPM ZE \ )
彼らは、全体として見ることができます。より良い後者の場合、それは確かに代替する前になります\(C \) だから、かつてのいくつかは優れています。
このカードは以上です。

その後、パーティションを検討してください。分割統治の焦点は、2つの間隔をマージについての答えです。
考えてみましょう\(S \)をするために転写した(S + 2 \)を\セットアップ転送\(S \)で左\(S_1 \)で右に1、\(S_2 \)ヶ月。
カテゴリー話と新たに挿入されたを参照してくださいには、次の3つの条件があるどちら側に2点を置きます:

  1. \(\ S_1 + 2) \(S_2 \)
  2. \(\ S_1 + 1) \(S_2 + 1 \)
  3. \(S_1 \) \(S_2 + 2 \)

上記の結論によると、いずれの場合においても周りも問題ありません。問題は、第二のケースということです。
ですので\(+ 1 \)ように、結論は使用できません。
しかし、私たちが発見、左の中で\(S1 \)または右\(S2 \)内の各プラグの状態、実際には、左の上で考えることができる\(S1 + 1 \)または右\(S2 + 1 \)の状態インチ すなわち、\(S1 + 1 \)は以上の状態であり、\は(S1 \)の状態遷移を越えて挿入されています。
したがって、この操作は効果がありません。


コード

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#define N 100010
int n,a[N];
int _fmn[N],_fmx[N];
int gmn[N],gmx[N];
inline int at(int *a,int x){return x?a[x]:0;}
void dfs(int l,int r){
    int *fmn=_fmn+l-1,*fmx=_fmx+l-1;
    if (l==r){
        fmn[1]=fmx[1]=a[l];
        return;
    } 
    int mid=l+r>>1;
    dfs(l,mid),dfs(mid+1,r);
    int *lmn=_fmn+l-1,*lmx=_fmx+l-1,*rmn=_fmn+mid,*rmx=_fmx+mid,s1=0,s2=0;
    for (int i=2;i<=r-l+1;i+=2){
        int ts1,ts2,v=INT_MIN;
        if (s2+2<=r-mid){
            int tmp=(s1&1?at(lmx,s1)-at(rmn,s2+2):at(lmx,s1)+at(rmx,s2+2));
            if (tmp>v)
                v=tmp,ts1=s1,ts2=s2+2;
        }
        if (s1+1<=mid-l+1 && s2+1<=r-mid){
            int tmp=(s1+1&1?at(lmx,s1+1)-at(rmn,s2+1):at(lmx,s1+1)+at(rmx,s2+1));
            if (tmp>v)
                v=tmp,ts1=s1+1,ts2=s2+1;
        }
        if (s1+2<=mid-l+1){
            int tmp=(s1+2&1?at(lmx,s1+2)-at(rmn,s2):at(lmx,s1+2)+at(rmx,s2));
            if (tmp>v)
                v=tmp,ts1=s1+2,ts2=s2;
        }
        gmx[i]=v;
        s1=ts1,s2=ts2;
    }
    s1=0,s2=0;
    for (int i=2;i<=r-l+1;i+=2){
        int ts1,ts2,v=INT_MAX;
        if (s2+2<=r-mid){
            int tmp=(s1&1?at(lmn,s1)-at(rmx,s2+2):at(lmn,s1)+at(rmn,s2+2));
            if (tmp<v)
                v=tmp,ts1=s1,ts2=s2+2;
        }
        if (s1+1<=mid-l+1 && s2+1<=r-mid){
            int tmp=(s1+1&1?at(lmn,s1+1)-at(rmx,s2+1):at(lmn,s1+1)+at(rmn,s2+1));
            if (tmp<v)
                v=tmp,ts1=s1+1,ts2=s2+1;
        }
        if (s1+2<=mid-l+1){
            int tmp=(s1+2&1?at(lmn,s1+2)-at(rmx,s2):at(lmn,s1+2)+at(rmn,s2));
            if (tmp<v)
                v=tmp,ts1=s1+2,ts2=s2;
        }
        gmn[i]=v;
        s1=ts1,s2=ts2;
    }
    if (lmx[1]>rmx[1])
        s1=1,s2=0,gmx[1]=lmx[1];
    else
        s1=0,s2=1,gmx[1]=rmx[1];
    for (int i=3;i<=r-l+1;i+=2){
        int ts1,ts2,v=INT_MIN;
        if (s2+2<=r-mid){
            int tmp=(s1&1?at(lmx,s1)-at(rmn,s2+2):at(lmx,s1)+at(rmx,s2+2));
            if (tmp>v)
                v=tmp,ts1=s1,ts2=s2+2;
        }
        if (s1+1<=mid-l+1 && s2+1<=r-mid){
            int tmp=(s1+1&1?at(lmx,s1+1)-at(rmn,s2+1):at(lmx,s1+1)+at(rmx,s2+1));
            if (tmp>v)
                v=tmp,ts1=s1+1,ts2=s2+1;
        }
        if (s1+2<=mid-l+1){
            int tmp=(s1+2&1?at(lmx,s1+2)-at(rmn,s2):at(lmx,s1+2)+at(rmx,s2));
            if (tmp>v)
                v=tmp,ts1=s1+2,ts2=s2;
        }
        gmx[i]=v;
        s1=ts1,s2=ts2;
    }
    if (lmn[1]<rmn[1])
        s1=1,s2=0,gmn[1]=lmn[1];
    else
        s1=0,s2=1,gmn[1]=rmn[1];
    for (int i=3;i<=r-l+1;i+=2){
        int ts1,ts2,v=INT_MAX;
        if (s2+2<=r-mid){
            int tmp=(s1&1?at(lmn,s1)-at(rmx,s2+2):at(lmn,s1)+at(rmn,s2+2));
            if (tmp<v)
                v=tmp,ts1=s1,ts2=s2+2;
        }
        if (s1+1<=mid-l+1 && s2+1<=r-mid){
            int tmp=(s1+1&1?at(lmn,s1+1)-at(rmx,s2+1):at(lmn,s1+1)+at(rmn,s2+1));
            if (tmp<v)
                v=tmp,ts1=s1+1,ts2=s2+1;
        }
        if (s1+2<=mid-l+1){
            int tmp=(s1+2&1?at(lmn,s1+2)-at(rmx,s2):at(lmn,s1+2)+at(rmn,s2));
            if (tmp<v)
                v=tmp,ts1=s1+2,ts2=s2;
        }
        gmn[i]=v;
        s1=ts1,s2=ts2;
    }
    for (int i=1;i<=r-l+1;++i)
        fmn[i]=gmn[i],fmx[i]=gmx[i];
}
int main(){
    freopen("pe.in","r",stdin);
    freopen("pe.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    dfs(1,n);
    for (int i=1;i<=n;++i)
        printf("%d ",_fmx[i]);
    return 0;
}

概要

結論は推測に頼ることです......

おすすめ

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