loj10008家庭作业
题目描述
老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为10 ,要求在6 天内交,那么要想拿到这 10 学分,就必须在第 6 天结束前交。
每个作业的完成时间都是只有一天。例如,假设有 7 次作业的学分和完成时间如下:
作业号 | 期限 | 学分 |
---|---|---|
1 | 1 | 6 |
2 | 7 | |
3 | 3 | 2 |
4 | 1 | |
5 | 2 | 4 |
6 | 5 | |
7 | 6 | 1 |
最多可以获得 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了!
___________________________________________
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }