2025杭电暑期联赛第四场(持续更新)

1008

狗日的被这题卡了:(

题意:给定一个长度为n的数组a。以及x>=y>=z三个参数
现在要求构造排列使数组重新排序
初始权值S为0

  • 当 a_p[i]>a_p[i-1] , S+=x
  • 当 a_p[i]=a_p[i-1] , S+=y
  • 当 a_p[i]<a_p[i-1] , S+=z
    求能构造的S的最大值

思路:
最初看到这题,排序显然不对
尝试使用multiset去贪心维护一些连续递增的段,然后只剩下一种数时把这种数塞到前面这种数旁边
然而超时
尝试用数组维护
然而Wa
尝试对拍
然而对不出来
因为本来两个想法都是错的 悲

最重要的一点是:在剩余一些数的时候,其实为它们单独开一个递增段不一定是优于把它们一股脑全部塞入前面已经有的序列中的

比如下列数据

1
6 15 15 1
1 2 2 3 3 4
90

显然最优策略是 :1 2 2 3 3 4
而非:1 2 3 4 2 3

剩下来就是细节和模拟了,注意一开始要加一个x

void solve(){
    int n,x,y,z;cin>>n>>x>>y>>z;
    vector<int>a(n+1);rep(i,1,n)cin>>a[i];
    vector<int>tot(n+1);
    vector<int>cnt(n+1);
    int res=0;
    rep(i,1,n){
        tot[a[i]]++;
    }
    rep(i,1,n){
        if(tot[i]){
            cnt[tot[i]]++;
            res++;
        }
    }
    int ans=0;
    int dif=0;
        int now=res;
        for(int i=1;i<=n;i++){
            ans+=max((res-1)*x+(i>=2?z:0),(i>=2)?y*res:0);
            res-=cnt[i];
            dif+=now;
            now-=(cnt[i]);
            if(res==0)break;
            if(res==1)break;
        }
    ans+=(n-dif)*y;
    cout<<ans+x<<endl;
}
posted @ 2025-07-28 18:53  Marinaco  阅读(29)  评论(0)    收藏  举报
//雪花飘落效果