책 세그먼트 트리 최적화 DP의 멀티 HDU 세 번째 보정 Hdu6606 배포

책의 Hdu6606 배포

문제의 의미

도면은 인접한 세그먼트 (K)으로 분할되고, 세그먼트 및 세그먼트 부분 사이에 빈 공간을 가질 수 있지만, 추구 부 접미사 번호를 절단 할 수 \ (최소 (최대 ((\ 합 AI)) \) 여기서 \ (\ 합 AI \)의 세그먼트 번호이고

분석

최소화 문제는 일반적으로 우리가 그것을 확인하는 방법 우리가 절반 생각해야 최대, 그래서 우리가 해결 답을 찾기위한 방법,하지만 절반? ? 내가이 전송 될 수있는 상황에서 세그먼트의 최대 개수, 어떻게 전송로 나눌 수 있습니다 - 몇 가지 아이디어, 우리는 알고리즘 폭력을 고려하지 않는이 시간, DP는 [I] (1)에서 나타내는 설정
분명히 \ (DP [I] = 최대 ( DP [J] + [합 [ I] -sum [J] <= X]) \) 우리 세그먼트에 일어날 수 있지만, 전사가 기록되도록 (2 N ^을 \ (O)를 \) 강력한 알고리즘 분명히 DP를 최적화하기 위해 이러한 어려움이 적용됩니다 주제의 복잡성 및 방법에 만족하지, DP 많은 단조로운 스택을 최적화하는 방법, 평행 사변형, 세그먼트 트리, 나무의 회장이있다.
: DP 최적화 정보 https://blog.csdn.net/qq_35649707/article/details/77834685
여기 값 천연 간격 비 분절 트리 이외 간격 확실히 문제가 없음을 부등식 부등식과 표시 범위를 만족되어 있기 때문이다. 불균등 의해 DP 값을 유지하기 위하여 우리는 최적 세그먼트 트리 이산 값의 세그먼트 가중치 합에 대응하는 트리 노드를 사용 \ ([I] [-sum 합계 J] <=의 X를 \) 우리 변환 \ ([I] 합 -x <= 합 [J] \) , 즉 단지 불평등 제 합을 찾아야 만족하고있다 (\ [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