标签:奋斗 优先 == 题解 cto 最大的 排列 -- pop
f[i]= max(f[i-r,i-r])+a[i]
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MARX=0xf;
int n,l,r,ans;
int a[300010];
int f[300010];
int main()
{
memset(f,-MARX,sizeof(f));//初始化极小值
ans=-2147483640;
f[0]=0;
scanf("%d%d%d",&n,&l,&r);
for(int i=0;i<=n;i++)
scanf("%d",&a[i]);
//===========输入与处理的境界============================
for(int i=1;i<=n;i++)
for(int j=i-r;j<=i-l;j++)//枚举能到达i点的每一个点
if(j>=0)//不出界
f[i]=max(f[i],f[j]+a[i]);
for(int i=n-r+1;i<=n;i++)//找到能到达对岸的点
ans=max(ans,f[i]);
printf("%d",ans);
}
时间复杂度为O(n*(r-l))
很遗憾,只有60分,TLE了4个点。
再 装上脑子 回头看该题的数据范围:
N<=200,000 且 1<= L<=R<=N
显然,上面O(n*(r-l))的时间复杂度, 会超到爆, 只有⑨才会用
对于第i个点与第i+1个点,
能到达第i个点的点在区间[ i-R , i-L ]中
能到达第i+1个点的点在区间[ i-R+1 , i-L+1 ]中
对于区间 [ i-R+1 , i-L+1 ],可以由区间[ i-R , i-L ]整体向右移动一位来得到.
这不禁让我们想到了另一道题目:P1886 滑动窗口
如果没有学习过单调队列,
推荐这篇文章:朝花中学OI队的奋斗历程——浅谈单调队列
学习一下单调队列。单调队列真是个好东西
PS:
//就相当于⑨做法的这里
for(int j=i-r;j<=i-l;j++) //枚举能到达i点的每一个点
if(j>=0)
f[i]=max(f[i],f[j]+a[i]);
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MARX=0xf;
int n,l,r,ans;
int a[300010];
int f[300010];
int queue[300010];
int head[300010];
int h=1,t=1;
int maxx(int i)//获取最大的f[i],单调队列模板
{
while(queue[t]<=f[i] && t>=h)
t--;
queue[++t]=f[i];//放入
head[t]=i;//记录序号
while(queue[h]+r<i)//删掉不能到达的
h++;
return head[h];//返回
}
int main()
{
memset(f,-MARX,sizeof(f));//初始化极小值
ans=-2147483640;
f[0]=0;
scanf("%d%d%d",&n,&l,&r);
for(int i=0;i<=n;i++)
scanf("%d",&a[i]);
for(int i=l;i<=n;i++)//DP过程
{
int k=maxx(i-l);
f[i]=f[k]+a[i];
if(i>=n-r+1)//找到能到达河对岸的,即答案
ans=max(ans,f[i]);
}
printf("%d",ans);
}
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int MARX=0xf;
int n,l,r,ans;
int a[300010];
int f[300010];
int h=1,t=1;
struct cmp1//自定义优先级,以冰冻指数和降序排列
{
bool operator ()(const int a,const int b)
{
return f[a]<f[b];
}
};
priority_queue < int,vector<int>,cmp1 > q;
int maxx(int i)//获取最大的f[x]
{
q.push(i);
while(q.top()+r<i)
q.pop();
return q.top();
}
int main()
{
memset(f,-MARX,sizeof(f));//初始化极小值
ans=-2147483640;
f[0]=0;
scanf("%d%d%d",&n,&l,&r);
for(int i=0;i<=n;i++)
scanf("%d",&a[i]);
for(int i=l;i<=n;i++)//DP过程
{
int k=maxx(i-l);
f[i]=f[k]+a[i];
if(i>=n-r+1)//找到能到达河对岸的,即答案
ans=max(ans,f[i]);
}
printf("%d",ans);
}
完成了这篇题解,车万厨信仰++
标签:奋斗 优先 == 题解 cto 最大的 排列 -- pop
原文地址:https://www.cnblogs.com/luckyblock/p/11456241.html