[Codeforces 28D] Do not fear,DravDe is kind

Posted NewErA

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Codeforces 28D] Do not fear,DravDe is kind相关的知识,希望对你有一定的参考价值。

Brief Intro:

对于四元组(v,c,l,r),求其子序列中v最大的和,并使其满足:

1、Ci+Li+Ri相同

2、L1=0,Rn=0

3、Li=Sigma(C1...Ci-1)

 

Solution:

算是有条件约束的DP吧

 

设dp[k]为选到k且选k的最大值

对于每个条件,我们这样处理:

1、将所有数据按Ci+Li+Ri的和进行分组处理

2、当Li=0时,将其视为起点;当Ri=0时,用dp[i]去更新res

3、此条件可转换为:仅当Lp=Lq+Cq时,dp[p]可由dp[q]转移而来

 

于是我们将数组按SUM排序后,用Best_val[t]记录Lk+Ck=t时最大的dp[k],用Best_id[t]记录Lk+Ck=t时最大的k,这样每次dp[k]由Best_val[Lk]更新,再由Best_id[Lk]更新父亲节点即可

 

#include <bits/stdc++.h>

using namespace std;

inline int read()
{
    char ch;int num,f=0;
    while(!isdigit(ch=getchar())) f|=(ch==-);
    num=ch-0;
    while(isdigit(ch=getchar())) num=num*10+ch-0;
    return f?-num:num;
}

template<class T> inline void putnum(T x)
{
    if(x<0)putchar(-),x=-x;
    register short a[20]={},sz=0;
    while(x)a[sz++]=x%10,x/=10;
    if(sz==0)putchar(0);
    for(int i=sz-1;i>=0;i--)putchar(0+a[i]);
    putchar( );
}

const int MAXN=1e5+10;
int n;
struct truck
{
    int v,c,l,r,num;
}dat[MAXN];
int pre[MAXN],dp[MAXN],b_val[MAXN],b_id[MAXN],T[MAXN],start=-1,res=0;

bool cmp(truck x,truck y)
{
    if(x.c+x.l+x.r==y.c+y.l+y.r) return x.num<y.num;
    return x.c+x.l+x.r<y.c+y.l+y.r;
}

int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        dat[i].v=read(),dat[i].c=read(),dat[i].l=read(),dat[i].r=read(),dat[i].num=i;
    
    sort(dat+1,dat+n+1,cmp);
    
    for(int i=1,j=1;i<=n;i=j)
    {
        while(j<=n && dat[i].c+dat[i].l+dat[i].r==dat[j].c+dat[j].l+dat[j].r) j++;
        for(int k=i;k<j;k++)
        {
            if(!dat[k].l) dp[k]=dat[k].v,pre[k]=-1;
            else if(T[dat[k].l]==i)
            {
                dp[k]=b_val[dat[k].l]+dat[k].v;
                pre[k]=b_id[dat[k].l];
            }
            
            int t=dat[k].l+dat[k].c;
            if(T[t]!=i || dp[k]>b_val[t])
            {
                b_val[t]=dp[k];T[t]=i;b_id[t]=k;
            }
            
            if(!dat[k].r && dp[k]>res) res=dp[k],start=k;
        }
    }
    
    vector<int> res;
    while(start!=-1) res.push_back(dat[start].num),start=pre[start];
    putnum(res.size());puts("");
    
    if(!res.size()) return 0;
    for(int i=res.size()-1;i>=0;i--) putnum(res[i]);
    return 0;
}

 

Review:

1、 注意子序列是不能改变相对次序的,因此排序时在SUM相同时要按原ID作为关键字排序(保证稳定性)

2、 对vector.size()少进行减法运算,防止unsigned int溢出

3、 对于具有决策单调性的DP,只要记录当前转移态前最优的状态即可

以上是关于[Codeforces 28D] Do not fear,DravDe is kind的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces - 1520A Do Not Be Distracted!

Codeforces Round #719 (Div. 3) A. Do Not Be Distracted!

CF28D Don't fear, DravDe is kind

Educational Codeforces Round28

笨办法学Python3——习题6 字符串和文本

Educational Codeforces Round20