[at4631]Jewels

如果要选某颜色,必然会选该颜色最大的两个,那么不妨将这两个宝石权值修改为两者的平均数,显然不影响两者的和,也即不影响答案

接下来,将所有宝石按权值从大到小排序,并在权值相同时按颜色编号从小到大(使颜色相同的在一起)

此时,如果可以选前$i$个宝石,那么显然直接选即可

否则,注由于每种颜色权值最大的两个宝石权值(和颜色)都相同,那么必然是相邻的,因此不能选的原因必然是第$i$个宝石的颜色在之前没有出现过

接下来,考虑先选前$i-1$个宝石,然后进行调整:

1.选择$i$之后(包括$i$)权值最大且该颜色之前选过的宝石

2.选择$i$之后(包括$i$)权值最大且颜色相同的两个宝石,并删除$i-1$之前(包括$i-1$)权值最小且该颜色选过不小于3次的宝石

3.选择$i$之后(包括$i$)权值最大且颜色相同的三个宝石,并删除$i-1$之前(包括$i-1$)权值最小且颜色相同的两个宝石

由于前面的宝石权值不小于后面,不难证明不会删更多的宝石,因此只有这三种情况,用set维护即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 200005
 4 #define ll long long
 5 vector<int>a[N];
 6 pair<int,int>b[N];
 7 multiset<int>S01,S11;
 8 multiset<ll>S02,S12,S13;
 9 int n,m,x,y,nn,vis[N];
10 ll sum,ans;
11 bool cmp(int x,int y){
12     return x>y;
13 }
14 int main(){
15     scanf("%d%d",&n,&m);
16     for(int i=1;i<=n;i++){
17         scanf("%d%d",&x,&y);
18         a[x].push_back((y<<1));
19     }
20     for(int i=1;i<=m;i++){
21         sort(a[i].begin(),a[i].end(),cmp);
22         if (a[i].size()){
23             y=(a[i][0]>>1)+(a[i][1]>>1);
24             a[i][0]=a[i][1]=y;
25             S12.insert(0LL+y+y);
26             if (a[i].size()>=3)S13.insert(0LL+y+y+a[i][2]);
27         }
28         for(int j=0;j<a[i].size();j++)b[++nn]=make_pair(-a[i][j],i);
29     }
30     sort(b+1,b+nn+1);
31     for(int i=1;i<=n;i++){
32         x=b[i].second;
33         if (vis[x]){
34             if (vis[x]>=2)S01.insert(a[x][vis[x]]);
35             if (vis[x]==1)S02.insert(0LL+a[x][vis[x]-1]+a[x][vis[x]]);
36             printf("%lld\n",(sum+a[x][vis[x]])/2);
37         }
38         else{
39             ans=-1e18;
40             if (!S11.empty())ans=(*--S11.end());
41             if ((!S01.empty())&&(!S12.empty()))ans=max(ans,(*--S12.end())-(*S01.begin()));
42             if ((!S02.empty())&&(!S13.empty()))ans=max(ans,(*--S13.end())-(*S02.begin()));
43             if (ans+sum<0)printf("-1\n");
44             else printf("%lld\n",(ans+sum)/2);
45         }
46         if (vis[x])S11.erase(S11.find(a[x][vis[x]]));
47         if (vis[x]+1<a[x].size())S12.erase(S12.find(0LL+a[x][vis[x]]+a[x][vis[x]+1]));
48         if (vis[x]+2<a[x].size())S13.erase(S13.find(0LL+a[x][vis[x]]+a[x][vis[x]+1]+a[x][vis[x]+2]));
49         sum+=a[x][vis[x]++];
50         if (vis[x]<a[x].size())S11.insert(a[x][vis[x]]);
51         if (vis[x]+1<a[x].size())S12.insert(0LL+a[x][vis[x]]+a[x][vis[x]+1]);
52         if (vis[x]+2<a[x].size())S13.insert(0LL+a[x][vis[x]]+a[x][vis[x]+1]+a[x][vis[x]+2]);
53     }
54 }
View Code

 

posted @ 2021-07-14 16:46  PYWBKTDA  阅读(93)  评论(0编辑  收藏  举报