loj10008家庭作业

题目描述

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

每个作业的完成时间都是只有一天。例如,假设有 7 次作业的学分和完成时间如下:

作业号期限学分
 1  1  6
 2
1
 4
 5
 6

最多可以获得 15 学分,其中一个完成作业的次序为 2,6,3,1,7,5,4,注意可能还有其他方法。

你的任务就是找到一个完成作业的顺序获得最大学分。

输入格式

第一行一个整数N ,表示作业的数量;

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

输出格式

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

样例

样例输入

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

样例输出

15

数据范围与提示

对于 100% 的数据,N<=1E6,作业的完成期限均小于7E5 

___________________________________________

这个题和10004是一样的,不同之处只是数据范围大很多。

按照原来的方法,有两个点不过。

加了一个fa[ ]数组,fa[i]表示i点前面一个没有被占用的时间,这样就成为了一片森林。只需要将他想并查集的压缩路径一样维护,就能避免过长的链。

然后就ok了!

___________________________________________

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e6+10;
 4 const int maxm=7e5+10;
 5 bool bz[maxm];
 6 int n,ans;
 7 struct node
 8 {
 9     int t,v;
10 }sz[maxn];
11 int fa[maxm];
12 bool cmp(node x,node y)
13 {
14     return x.v>y.v;
15 }
16 int find(int x)
17 {
18     if(bz[fa[x]]==0)return fa[x];
19     else return fa[x]=find(fa[x]);
20 }
21 int main()
22 {
23     scanf("%d",&n);
24     for(int i=1;i<=n;++i)scanf("%d%d",&sz[i].t,&sz[i].v);
25     for(int i=1;i<=700000;++i)fa[i]=i;
26     sort(sz+1,sz+1+n,cmp);
27     for(int x,y,i=1;i<=n;++i)
28     {
29         x=sz[i].t;y=sz[i].v;
30         bool bzt=0;
31         int fat=find(x);
32         if(fat!=0)
33         {
34             bzt=1;
35             bz[fat]=1;
36             fa[fat]=fa[fat-1];
37         }
38         if(bzt)ans+=y;
39     }
40     cout<<ans;
41     return 0;
42 }
View Code

 

posted on 2020-11-12 10:12  gryzy  阅读(147)  评论(0编辑  收藏  举报

导航