1. 程式人生 > >codeforces+C. Multi-Subject Competition+技巧

codeforces+C. Multi-Subject Competition+技巧

題目連結: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;
}