传送门
思路:
先按学分从大到小排序,根据贪心的思想尽可能地让作业的完成时间延后,这样就能有更多空间给那些限制比较严格的作业
设 f [ i ] 为点 i 向左的最小空闲时间
对于一个限制 t 的作业,我们将它放在 f [ t ] 上,同时使 f [ t ] = f [ t ] - 1(表示这个时间被占用了)
再用并查集维护一下。
Code:
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<cstdlib> #include<stack> #include<vector> #include<queue> #include<deque> #include<map> #include<set> using namespace std; #define lck_max(a,b) ((a)>(b)?(a):(b)) #define lck_min(a,b) ((a)<(b)?(a):(b)) typedef long long LL; const int maxn=1e6+7; LL n,ans,maxx,fa[maxn]; struct hh { LL w,las; }t[maxn]; inline LL read() { LL kr=1,xs=0; char ls; ls=getchar(); while(!isdigit(ls)) { if(!(ls^45)) kr=-1; ls=getchar(); } while(isdigit(ls)) { xs=(xs<<1)+(xs<<3)+(ls^48); ls=getchar(); } return xs*kr; } inline void out(LL xs) { if(!xs) {putchar(48); return;} if(xs<0) putchar('-'),xs=-xs; int kr[57],ls=0; while(xs) kr[++ls]=xs%10,xs/=10; while(ls) putchar(kr[ls]+48),ls--; } inline bool cmp(const hh&a,const hh&b) { return a.w>b.w; } inline LL find(LL u) { return u==fa[u]?u:fa[u]=find(fa[u]); } int main() { n=read(); for(LL i=1;i<=n;i++) t[i].las=read(),t[i].w=read(),maxx=lck_max(maxx,t[i].las); for(LL i=1;i<=maxx;i++) fa[i]=i; sort(t+1,t+n+1,cmp); for(LL i=1;i<=n;i++) { LL lck=find(t[i].las); if(lck) ans+=t[i].w,fa[lck]=lck-1; } out(ans),putchar(' '); return 0; }