Recommendations CodeForces - 1315D(并查集+贪心)

VK news recommendation system daily selects interesting publications of one of n disjoint categories for each user. Each publication belongs to exactly one category. For each category i batch algorithm selects ai publications.

The latest A/B test suggests that users are reading recommended publications more actively if each category has a different number of publications within daily recommendations. The targeted algorithm can find a single interesting publication of i-th category within ti seconds.

What is the minimum total time necessary to add publications to the result of batch algorithm execution, so all categories have a different number of publications? You can’t remove publications recommended by the batch algorithm.

Input
The first line of input consists of single integer n — the number of news categories (1≤n≤200000).

The second line of input consists of n integers ai — the number of publications of i-th category selected by the batch algorithm (1≤ai≤109).

The third line of input consists of n integers ti — time it takes for targeted algorithm to find one new publication of category i (1≤ti≤105).

Output
Print one integer — the minimal required time for the targeted algorithm to get rid of categories with the same size.

Examples
Input
5
3 7 9 7 8
5 2 5 7 5
Output
6
Input
5
1 2 3 4 5
1 1 1 1 1
Output
0
Note
In the first example, it is possible to find three publications of the second type, which will take 6 seconds.

In the second example, all news categories contain a different number of publications.
思路:一开始用的离散化+线段树,但是离散化应该是有点错误,结果不对。而线段树无法承担高额的空间,所以只好作罢。对于数量相同的,我们应该怎样排序,才能使得最终结果最小呢?我们可以比较一下,按照时间由大到小的顺序排序是最优的。拍完序之后,我们利用并查集去查找符合这个数量的最小值,然后与当前的数量差值乘以时间作为答案贡献。
代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxx=2e5+100;
const int maxn=4e5+100;
struct node{
	ll num,v;
	bool operator<(const node &a)const{
		if(v!=a.v) return v>a.v;
		else return num<a.num;
	}
}pp[maxx];
map<ll,ll> f;
int n;

inline ll getf(ll u)
{
	if(!f[u]) return u;
	else return f[u]=getf(f[u]);
}
inline void merge(ll u,ll v)
{
	ll t1=getf(u);
	ll t2=getf(v);
	if(t1!=t2) f[t1]=t2;
}
int main()
{
	scanf("%d",&n);
	ll tmp;
	f.clear();
	for(int i=1;i<=n;i++) scanf("%lld",&pp[i].num);
	for(int i=1;i<=n;i++) scanf("%lld",&pp[i].v);
	sort(pp+1,pp+1+n);
	ll ans=0;
	for(int i=1;i<=n;i++)
	{
		tmp=getf(pp[i].num);
		ans+=pp[i].v*(tmp-pp[i].num);
		merge(tmp,tmp+1);
	}
	cout<<ans<<endl;
	return 0;
}

努力加油a啊,(o)/~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

starlet_kiss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值