地址:http://codeforces.com/contest/1082/problem/C
思路:前缀和,将同一个项目的得分按照由大到小排序,再将每个项目按照得分个数由大到小排序,遍历项目,用pre[i]表示每个项目选i个分数的最大价值,遍历k项目时,用bb[i]保存前缀和,在将为正值的加入pre[i]中,同时ans保存最大pre[i]即可
Code:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
typedef long long LL;
const int MAX_N=1e5+5;
struct node{
int x;
int id;
bool operator<(const node &p)const{
return x>p.x;
}
};
int n,m;
node a[MAX_N];
vector<LL> d[MAX_N];
LL pre[MAX_N],bb[MAX_N];
bool cmp(const LL &a,const LL &b) {
return a>b;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
int x,y;
for(int i=0;i<n;++i)
{
cin>>x>>y;
d[x].push_back(y);
}
for(int i=1;i<=m;++i)
{
a[i].id=i; a[i].x=d[i].size();
if(a[i].x) sort(d[i].begin(),d[i].end(),cmp);
}
sort(a+1,a+m+1);
LL ans=0;
for(int i=1;i<=m;++i)
{
int id=a[i].id,s=a[i].x;
if(!s) break;
bb[0]=d[id][0];
for(int j=1;j<s;++j)
bb[j]=bb[j-1]+d[id][j];
for(int j=0;j<s;++j)
{
if(bb[j]<0) break;
pre[j]+=bb[j];
ans=max(ans,pre[j]);
}
}
cout<<ans<<endl;
return 0;
}