题目链接:http://codeforces.com/problemset/problem/1082/C
题目大意:

有n个人,m个竞赛,(1≤n≤10^5, 1≤m≤10^5)
每个人熟悉一个竞赛si,并且熟悉的本领为ri(ri可以为负)
现在让你选择去参加竞赛的人,对应选择的要求:对于有人去的这些竞赛,去的人数必须相同,有的竞赛可以没人去。

问你去的人的本领总和最大是多少?

思路:

但是复杂度为O(n*m)。
但是可以用边求前缀和边求C[i]数组,复杂度为O(n)

 for(int i=1;i<=m;i++)
    {
        sort(v[i].begin(), v[i].end(), ru);//排序
        long long s=0;
        for(int j=0;j<v[i].size();j++)
        {
            s+=v[i][j];
            if(s>0)/*如果前缀和>0那么选择j个人,一定会选这个学科,所以c[j]+=s;*/
                c[j]+=s;
            else
                break;
        }
    }

思路:一个好的技巧

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 100005;

vector<int> v[N];
ll c[N];
int ru(int a, int b){return a>b;}

int main()
{
    fill(c, c+N, 0);
    int n, m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
    {
        int x, y;
        scanf("%d%d",&x, &y);
        v[x].push_back(y);
    }
    
    for(int i=1;i<=m;i++)
    {
        sort(v[i].begin(), v[i].end(), ru);//排序
        long long s=0;
        for(int j=0;j<v[i].size();j++)
        {
            s+=v[i][j];
            if(s>0)/*如果前缀和>0那么选择j个人,一定会选这个学科,所以c[j]+=s;*/
                c[j]+=s;
            else
                break;
        }
    }
    cout<<*max_element(c, c+100002)<<endl;

	return 0;
}