P10977 Cut the Sequence
P10977 Cut the Sequence
看到题目我们不难想到动态规划,对于每一个点 \(a_i\) 可以求一个 \(pre_i\) 满足 $ \forall j \in[pre_i+1,i]$ $a_l \le a_i $ 且 $ a_i<a_{pre_i} $ 用人话说就是从 \(i\) 往前数第一个大于 \(a_i\) 的数,然后我们可以对于 \(a_i\) 求一个前缀和,这样就能找到对于 \(a_i\) 来说最后一个合法的点 \(lim\)
然后我们思考一下状态转移:
\(f_i= \min(f[j]+ \max a_k) j \in [lim+1,i] k\in [j+1,i]\)
然后我们会发现右边那个东西可以用线段树来维护,\(f\) 支持单点修改,\(max\) 支持区间赋值
开一个线段树维护三个数:\(f,mi,ans\) 分别表示区间内最小化的 \(f\) ,最小化后的 \(max\) ,和区间答案
对于每个点 \(a_i\) 我们先将线段树上点 \(i\) 的权值更新为 \(f_{i-1}\) 然后更新 \([pre,i]\) 区间的 \(max\) 为 \(a_i\)
然后直接在线段树上查询 \(f_i\) 就好了
然后这题就愉快的做完了
Code:
#include<bits/stdc++.h>
#define ll long long
const int N=1e5+5;
const ll inf=1e17;
using namespace std;
//Segment_Tree
#define ls x<<1
#define rs x<<1|1
struct Segmeng_Tree{
struct Tree{
ll ans,f,mi;
int l,r;
}t[N<<2];
void pushup(int x)
{
t[x].ans=min(t[ls].ans,t[rs].ans);
t[x].f=min(t[ls].f,t[rs].f);
return;
}
void upd(int x){t[x].ans=t[x].f+t[x].mi;}
void pushdown(int x)
{
if(t[x].mi==inf)return ;
t[ls].mi=t[rs].mi=t[x].mi;
upd(ls);upd(rs);
t[x].mi=inf;
}
void build(int x,int l,int r)
{
t[x]=(Tree){inf,inf,inf,l,r};
if(l==r)return;
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
}
void upd_mi(int x,int L,int R,ll mi)
{
if(L<=t[x].l&&t[x].r<=R)
{
t[x].mi=mi;
upd(x);
return;
}
int mid=t[x].l+t[x].r>>1;
pushdown(x);
if(L<=mid)upd_mi(ls,L,R,mi);
if(mid<R) upd_mi(rs,L,R,mi);
pushup(x);
}
void upd_f(int x,int pos,ll w)
{
if(t[x].l==t[x].r)
{
t[x].f=w;
return ;
}
int mid=t[x].l+t[x].r>>1;
pushdown(x);
if(pos<=mid)upd_f(ls,pos,w);
if(mid<pos) upd_f(rs,pos,w);
pushup(x);
}
ll query(int x,int L,int R)
{
if(L<=t[x].l&&t[x].r<=R)
{
return t[x].ans;
}
int mid=t[x].l+t[x].r>>1;
pushdown(x);
ll res=inf;
if(L<=mid)res=min(res,query(ls,L,R));
if(mid<R) res=min(res,query(rs,L,R));
return res;
}
}T;
#undef ls
#undef rs
//Segment_Tree
int n,m,st=1,ed=0;
int q[N],pre[N];
ll a[N],sum[N],f[N];
void work()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
if(a[i]>m){cout<<"-1";return;}
while(st<=ed&&a[q[ed]]<a[i]){
ed--;
}
pre[i]=q[ed];
q[++ed]=i;
sum[i]=sum[i-1]+a[i];
}
T.build(1,1,n);
//return;
for(int i=1;i<=n;i++)
{
T.upd_f(1,i,f[i-1]);
if(pre[i]<i)T.upd_mi(1,pre[i]+1,i,a[i]);
int l=lower_bound(sum,sum+1+i,sum[i]-m)-sum;// sum[i]-sum[l]>m
if(l<i)f[i]=T.query(1,l+1,i);
}
printf("%lld",f[n]);
}
int main()
{
//freopen("P10977.in","r",stdin);
//freopen("P10977.out","w",stdout);
work();
}

浙公网安备 33010602011771号