本セグメントツリーの最適化DPのマルチHDU第3の補正Hdu6606配布

図書のHdu6606配布

問題の意味

この図は、連続するセグメントkに分割されたセグメントとセグメントとセクションの間に自由空間を持つことができないが、シーク、部分サフィックス番号を切り捨てることができる\(MIN(MAX((\和AI))\) \(\を合計AI \)は、セグメント番号で、

分析

最小化問題は通常、我々は半分考える必要が最大、私たちが解決の答えを見つけるための方法が、私たちはそれを確認する方法の半分ですか??私はそれを転送することができますどのような状況の下でセグメントの最大数、どのように転送、に分けることができます-いくつかのアイデアは、我々はアルゴリズムの暴力を考慮していないこの時間は、DP [i]が1から表しセット
どうやら\(DP [I] =マックス ( DP [J] + [合計[ i]は-sum [J] <= X])\) 私たちは、セグメントまで得ることができるように、しかし、転送が書かれている\(O(N ^ 2) \) 暴力的なアルゴリズム、どうやらDPを最適化するために、この問題の対象となる話題の複雑さ、そしてどのように満足していない、DP多くの単調なスタックを最適化する方法、平行四辺形、セグメントツリー、木の会長があります。
:DPの最適化についてhttps://blog.csdn.net/qq_35649707/article/details/77834685
ここで値が自然区間、非セグメントツリー以外の間隔確かに問題なしと不平等、格差と示された範囲を満たすされているため。不等によってDPの値を維持するように、我々は、最適化セグメントツリー、離散値のセグメントの重み和を対応するツリーノードを使用\([I] [-sum合計 J <= xを\) 、我々はに変換\ ([i]の総和を-x <=和[J] \) 即ちだけ不等式の第1の和を見つける必要があり、次いで、満たされ([J、M] \ \ ) DPの最大値を探しでは、の複雑さを転送することができます最適化する\(O(nlognlogn)= O (nlog ^ 2n個)\)

#include<bits/stdc++.h>
#define pb push_back
#define F first
#define S second
#define pii pair<int,int>
#define mkp make_pair
typedef long long ll;
using namespace std;
const int maxn=2e5+5;
int tr[maxn<<2];
int a[maxn];
ll sum[maxn],v[maxn];
int t,n,k,flag,cnt=0,sz;
void build(int o,int l,int r){
    tr[o]=-maxn;
    if(l==r)return ;
    int mid=l+r>>1;
    build(o<<1,l,mid);
    build(o<<1|1,mid+1,r);
}
void update(int o,int l,int r,int p,int v){
    if(l==r)tr[o]=max(tr[o],v);
    else {
        int mid=l+r>>1;
        if(mid>=p)update(o<<1,l,mid,p,v);
        else update(o<<1|1,mid+1,r,p,v);
        tr[o]=max(tr[o<<1],tr[o<<1|1]);
    }
}
int query(int o,int l,int r ,int x,int y){
    if(x<=l&&y>=r)return tr[o];
    int mid=l+r>>1;
    int ans=-maxn;
    if(mid>=x)ans=max(ans,query(o<<1,l,mid,x,y));
    if(mid<y)ans=max(ans,query(o<<1|1,mid+1,r,x,y));
    return ans;
}
bool  check(ll x){
    build(1,1,sz);
    for(int i=1;i<=n;i++){
        int l=lower_bound(v+1,v+1+sz,sum[i]-x)-v;
        int id=lower_bound(v+1,v+1+sz,sum[i])-v;
        //cout<<" i "<<i<<" l "<<l<<" id "<<id<<" sum-x "<<sum[i]-x<<endl;
        if(l>sz){
            if(sum[i]<=x)
            update(1,1,sz,id,1);
        }
        else {
            int t=query(1,1,sz,l,sz);
            //cout<<i<<" t "<<t<<endl;
            if(t==-maxn){
                if(sum[i]<=x)
                update(1,1,sz,id,1);
            }
            else 
            update(1,1,sz,id,t+1);
        }
    }
    //cout<<query(1,1,sz,1,sz)<<endl;
    return query(1,1,sz,1,sz)>=k;
}
int main(){
    scanf("%d",&t);
    while(t--){
        cnt=1;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
            v[cnt++]=(sum[i]);
        }
        cnt--;
        sort(v+1,1+v+cnt);
        sz=unique(v+1,v+1+cnt)-v-1;
    //  for(int i=1;i<=sz;i++)cout<<v[i]<<" ";
    //  cout<<endl;
        //cout<<sz<<endl;
        ll l=-1e14;
        ll r=-l;
        ll ans=1e15;
        while(l<=r){
            ll mid=l+r>>1;
            //cout<<l<<" "<<r<<endl;
            if(check(mid)){
                ans=min(ans,mid);
                r=mid-1;
            }
            else l=mid+1;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/ttttttttrx/p/11310867.html