D - Various Sushi


Time Limit: 2 sec / Memory Limit: 1024 MB

Score : <var>400400</var> points

Problem Statement

There are <var>NN</var> pieces of sushi. Each piece has two parameters: "kind of topping" <var>titi</var> and "deliciousness" <var>didi</var>. You are choosing <var>KK</var> among these <var>NN</var> pieces to eat. Your "satisfaction" here will be calculated as follows:

  • The satisfaction is the sum of the "base total deliciousness" and the "variety bonus".
  • The base total deliciousness is the sum of the deliciousness of the pieces you eat.
  • The variety bonus is <var>xxx∗x</var>, where <var>xx</var> is the number of different kinds of toppings of the pieces you eat.

You want to have as much satisfaction as possible. Find this maximum satisfaction.

Constraints

  • <var>1KN1051≤K≤N≤105</var>
  • <var>1tiN1≤ti≤N</var>
  • <var>1di1091≤di≤109</var>
  • All values in input are integers.

Input

Input is given from Standard Input in the following format:

<var>NN</var> <var>KK</var>
<var>t1t1</var> <var>d1d1</var>
<var>t2t2</var> <var>d2d2</var>
<var>..</var>
<var>..</var>
<var>..</var>
<var>tNtN</var> <var>dNdN</var>

Output

Print the maximum satisfaction that you can obtain.


Sample Input 1 Copy

Copy
5 3
1 9
1 7
2 6
2 5
3 1

Sample Output 1 Copy

Copy
26

If you eat Sushi <var>1,21,2</var> and <var>33</var>:

  • The base total deliciousness is <var>9+7+6=229+7+6=22</var>.
  • The variety bonus is <var>22=42∗2=4</var>.

Thus, your satisfaction will be <var>2626</var>, which is optimal.


Sample Input 2 Copy

Copy
7 4
1 1
2 1
3 1
4 6
4 5
4 5
4 5

Sample Output 2 Copy

Copy
25

It is optimal to eat Sushi <var>1,2,31,2,3</var> and <var>44</var>.


Sample Input 3 Copy

Copy
6 5
5 1000000000
2 990000000
3 980000000
6 970000000
6 960000000
4 950000000

Sample Output 3 Copy

Copy
4900000016

Note that the output may not fit into a <var>3232</var>-bit integer type.

 题意:

给定N个结构体,每一个结构体有两个信息,分别是type  和 x,让你从中选出K个结构体,

使之type的类型数的平方+sum{ xi } 最大。

思路:

可以贪心来做。

首先根据x由大到小来排序,然后选入结构体,先贪心的全前K个,把每一种类型的第一个一定的加入到我们选择的范围中,(贪心思想)

然后把某一种类型的后面几个的结构体加入到栈中,

然后扫k+1~n的时候,如果这个结构体的类型没加入过,那么把他加入,然后类型数目+1,弹出栈顶的元素,减去他的x值贡献,然后用新结构体取尝试更新最大值。

还主要用到了stack的先进后出的思想,巧妙的最优的替换了每一个能替换掉的是当前选择中贡献最小的。

贪心好题,(口胡结束)。细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#define rt return
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
inline void getInt(int* p);
const int maxn=1000010;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int n,k;
struct info
{
    int x,v;
}a[maxn];
bool cmp(info one,info two)
{
    return one.v>two.v;
}
int vis[maxn];
stack<int> s;
int main()
{
    scanf("%d %d",&n,&k);
    repd(i,1,n)
    {
        scanf("%d %d",&a[i].x,&a[i].v);
    }
    sort(a+1,a+1+n,cmp);
    ll cnt=0;
    ll tp=0;
    ll res=0;
    ll ans=0ll;
    repd(i,1,n)
    {
        if(cnt<k)
        {
                if(vis[a[i].x]==0)
                {
                    vis[a[i].x]=1;
                    tp++;
                }else
                {
                    s.push(a[i].v);
                }
                res+=a[i].v;
                cnt++;
                ans=max(ans,res+1ll*tp*tp);
        }
        else{
            if(s.empty())
                break;
            if(vis[a[i].x])
                continue;
            vis[a[i].x]=1;
            tp++;
            res-=s.top();
            res+=a[i].v;
            s.pop();
            ans=max(ans,res+tp*tp);
        }
    }
    printf("%lld\n",ans);
    return 0;
}

inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    }
    else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}