洛谷p2564生日礼物andp2627修建草坪

单调队列

修建草坪:

(

对于后面这一坨ee,我们可以用前缀和优化:

dp_i=max(dp_j-sum_j+sum_{i-1})dpi=max(dpjsumj+sumi1)

但是还是会TLETLE。

我们发现,max(dp_j-sum_j)max(dpjsumj)只与jj有关,我们考虑单调队列优化。

我们设a_jaj表示dp_j-sum_jdpjsumj,如果x<yx<y且a_x\leq a_{y}axay,那么xx不会用来更新。

状态zz用来更新dpdp数组。z_1……z_pz1zp满足:z_i>z_{i-1}zi>zi1a_{z_i}>a_{z_{i-1}}azi>azi1

对于一个新的状态zz,如果队首不满足a_{z_i}> a_zazi>az就出队直到满足,同时要注意队尾的边界问题。

代码:

#include<bits/stdc++.h>
using namespace std;
long long v[210000],q[110000],dp[210000],n,m,ans,sum[210000];
int main()
{
scanf("%lld%lld",&n,&m);
for(long long i=1;i<=n;i++)
{
scanf("%lld",&v[i]);
sum[i]+=(sum[i-1]+v[i]);
}
//dp[i]=max(dp[j]+sum[i]-sum[j]) i-k<=j<=i
long long head=1,tail=1; //q保留优质值的编号
for(long long i=1;i<=n+1;i++)
{
while(q[head]<i-m-1&&head<=tail) head++;
dp[i]=max(dp[i],dp[q[head]]+sum[i-1]-sum[q[head]]);
ans=max(ans,dp[i]);
while(dp[q[tail]]-sum[q[tail]]<=dp[i]-sum[i]&&head<=tail) tail--;
q[++tail]=i;
}
cout<<ans;
return 0;
}

生日礼物:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<deque>
#include<vector>
#include<algorithm>
using namespace std;
struct data
{
int kind;
int pos;
};
data que[2100000];
int ans=1e9,n,k,tot,l,r,len,xx[2100000];
bool cmp(data qq,data ww){return qq.pos<ww.pos;}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++)
{
int qq;
scanf("%d",&qq);
for(int j=1;j<=qq;j++)
{
int ww;
scanf("%d",&ww);
que[++tot].pos=ww;
que[tot].kind=i;
}
}
sort(que+1,que+1+n,cmp);
len=que[n].pos-que[1].pos;
int cnt=0;
l=1;
memset(xx,-1,sizeof(xx));
for(int i=1;i<=n;i++)
{
if(xx[que[i].kind]==-1) cnt++;
xx[que[i].kind]=que[i].pos;
while(l<=i&&que[l].pos!=xx[que[l].kind]) l++;
if(cnt==k) len=min(len,que[i].pos-que[l].pos);
}
cout<<len;
return 0;
}

posted on 2019-07-14 10:38  GdAGt  阅读(100)  评论(0编辑  收藏  举报

导航