題意:給出10000個任務,每個任務告訴你收益pi和截止日期di,然後求最大收益。。。
分析:以前做過的,突然發現忘了當時並查集怎麼做的。。。水啊。。。
其實就是貪心,按照收益從大到小排序,然後每次選最大的那個去填可以填的最大的一個時間。。。這個時間可以用並查集來維護,最開始每天都指向自己,當某一天被用之後就指向前一天,(或者可以直接指向前一天指向的那一天---沒必要)。。。當然find爲0的無視掉就好了。。。。
其實這個很顯然也可以用線段樹維護這個最大值,但時間慢太多了。。。
並查集代碼:
#include<iostream>
#include<algorithm>
using namespace std;
const int N=10010;
int n, m, sum, f[N];
struct node
{
int p, d;
} a[N];
int cmp(const node &a, const node &b)
{
return a.p > b.p;
}
int findf(int x)
{
if(f[x]!=x)
f[x] = findf(f[x]);
return f[x];
}
void unionf(int x, int y)
{
int fx = findf(x);
int fy = findf(y);
if(fx!=fy)
{
f[fx] = fy;
}
}
int main()
{
int i, j, k, x, y, tmp, mx;
while(scanf("%d", &m)!=EOF)
{
mx = 0;
for(i=0; i<m; i++)
{
scanf("%d%d", &a[i].p, &a[i].d);
if(mx<a[i].d)
mx = a[i].d;
}
for(i=0; i<=mx; i++)
{
f[i] = i;
}
sort(a, a+m, cmp);
sum = 0;
for(i=0; i<m; i++)
{
tmp = findf(a[i].d);
if(tmp>0)
{
sum += a[i].p;
unionf(tmp, tmp-1);
}
}
printf("%d\n", sum);
}
return 0;
}