如果要选某颜色,必然会选该颜色最大的两个,那么不妨将这两个宝石权值修改为两者的平均数,显然不影响两者的和,也即不影响答案
接下来,将所有宝石按权值从大到小排序,并在权值相同时按颜色编号从小到大(使颜色相同的在一起)
此时,如果可以选前$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 ",(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 "); 44 else printf("%lld ",(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 }