【贪心】家庭作业 【链表优化】

题目描述

老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为10,要求在6天内交,那么要想拿到这10学分,就必须在第6天结束前交。
每个作业的完成时间都是只有一天。例如,假设有7次作业的学分和完成时间如下:

老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为10,要求在6天内交,那么要想拿到这10学分,就必须在第6天结束前交。
每个作业的完成时间都是只有一天。例如,假设有7次作业的学分和完成时间如下:

输入

第一行一个整数N,表示作业的数量;
接下来N行,每行包括两个整数,第一个整数表示作业的完成期限,第二个数表示该作业的学分。

输出

输出一个整数表示可以获得的最大学分。保证答案不超过C/C++的int范围。

样例输入

7
1 6
1 7
3 2
3 1
2 4
2 5
6 1

样例输出

15

提示

对于20%的数据,N≤103;
对于40%的数据,N≤104;
对于60%的数据,N≤105;
对于100%的数据,N≤106,作业的完成期限均小于7×105

 
分析:
优先选择分高的,所以先根据分数从高到低排序,然后预处理链表为:每一天指向最近的空闲的前一天
然后遍历一次 若可以 则更新链表
 
代码:
#include <bits/stdc++.h>

using namespace std;

const int maxn = 1000005;
int pre[maxn];
bool vis[maxn]={0};

struct node{
    int d,v;
}a[maxn];
int cmp(node x,node y)
{
    if(x.v!=y.v)
        return x.v>y.v;
    else
        return x.d>y.d;
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}

int findfa(int x)
{
    if(!vis[x])
        return x;
    else
        return pre[x] = findfa(pre[x]);
}

int main(){
    int n;
    n = read();
    for(int i=0;i<n;i++){
        a[i].d = read();
        a[i].v = read();
    }
    sort(a,a+n,cmp);
    for(int i=1;i<=700000;i++)
        pre[i] = i-1;
    int ans = 0;
    int pre_pos;
    for(int i=0;i<n;i++)
    {
        pre_pos = findfa(a[i].d);
        if(pre_pos==0)
            continue;
        else
        {
            vis[pre_pos] = 1;
            ans+=a[i].v;
        }
    }
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/hao-tian/p/10392399.html