一、题目
二、解法
首先
相同的分到一组,最优解一定只能出现在某一组内,每一组内单独做
,设
为前面包括自己的人数和为
的最大权值,每次只需要更新一次,所以时间复杂度是
的,转移:
最后找出最优的那一组,再跑一遍还原路径即可。
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int M = 300005;
const int inf = 0x3f3f3f3f;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,mx,cur,dp[M],fa[M],k[M],ans[M];
struct node
{
int v,c,l,r,id;
};vector<node> a[M];
void print(int x)
{
if(x==-1) return ;
print(fa[x]);
printf("%d ",a[cur][x].id);
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
int v=read(),c=read(),l=read(),r=read();
a[l+c+r].push_back(node{v,c,l,r,i});
}
memset(dp,-0x3f,sizeof dp);
dp[0]=0;
for(int i=1;i<=300000;i++)
{
for(int j=0;j<a[i].size();j++)
dp[a[i][j].c+a[i][j].l]=max(dp[a[i][j].c+a[i][j].l],dp[a[i][j].l]+a[i][j].v);
if(dp[i]>mx)
{
mx=dp[i];
cur=i;
}
for(int j=0;j<a[i].size();j++)
dp[a[i][j].c+a[i][j].l]=-inf;
}
memset(k,-1,sizeof k);
memset(fa,-1,sizeof fa);
for(int i=cur,j=0;j<a[i].size();j++)
{
if(dp[a[i][j].c+a[i][j].l]<dp[a[i][j].l]+a[i][j].v)
{
dp[a[i][j].c+a[i][j].l]=dp[a[i][j].l]+a[i][j].v;
fa[j]=k[a[i][j].l];
k[a[i][j].c+a[i][j].l]=j;
ans[a[i][j].c+a[i][j].l]=ans[a[i][j].l]+1;
}
}
printf("%d\n",ans[cur]);
print(k[cur]);
}