책의 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;
}