P10977 Cut the Sequence
P10977 Cut the Sequence
看到题目我们不难想到动态规划,对于每一个点
然后我们思考一下状态转移:
然后我们会发现右边那个东西可以用线段树来维护,
开一个线段树维护三个数:
对于每个点
然后直接在线段树上查询
然后这题就愉快的做完了
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(); }