社区讨论

神秘小贪心 75pts 求 hack

P6155修改参与者 2已保存回复 4

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
4 条
当前快照
1 份
快照标识符
@mihk8nv7
此快照首次捕获于
2025/11/27 23:00
3 个月前
此快照最后确认于
2025/11/29 11:40
3 个月前
查看原帖
rt,思路是统计每种数最终会归属到多大的数,然后贪心策略 \rightarrow 尽量让小的数往最大走,保证多取的尽量多,然后再留一些是跟上一级数的差,即不会卷进上一级里的部分,然后分别统计这两种,把 nn 个操作次数排序,递减跟递增配对。
不知道是想假了还是写挂了,样例全过。
CPP
/*
重要结论:总操作次数不变
∴多的尽量多
先排序,统计每种数的增加上限(最终最大的那个数的值)和增加下限(与下一种数的差)
*/
#include<bits/stdc++.h>
using namespace std;
constexpr int N=1000006;
unsigned n,m,a[N],f[N],tot;
unsigned long long b[N],lim[N],d[N],use[N],ans;
unordered_map<unsigned,int>cnt;
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i],cnt[a[i]]++;
    for(int i=1;i<=n;i++)cin>>b[i];
    sort(a+1,a+1+n),sort(b+1,b+1+n);
    m=unique(a+1,a+1+n)-a-1;
    for(int i=m;i;i--){
    	f[i]=i,lim[i]=a[i]+cnt[a[i]]-1;
    	if(i<m&&lim[i]>=a[i+1])f[i]=f[i+1],lim[f[i]]+=lim[i]-a[i+1]+1,d[i]=a[i+1]-a[i];
    	else d[i]=cnt[a[i]];
	}
	for(int i=1;i<=m;i++){
		while(cnt[a[i]]>d[i]){
			use[++tot]=lim[f[i]]-a[i];
			lim[f[i]]--;
			cnt[a[i]]--;
		}
		while(d[i]--)use[++tot]=d[i];
	}
	sort(use+1,use+1+n);
	for(int i=n;i;i--)ans+=b[i]*use[n-i+1];
	cout<<ans;
    return 0;
}

回复

4 条回复,欢迎继续交流。

正在加载回复...