题意:给出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;
}