VEXOBEN
Vexoben
Feb 10, 2018
It takes 2 minutes to read this article.

题目链接:http://codeforces.com/problemset/problem/367/C

题意

给出m个不同的数,并且每个数都有个费用,现在要在m个数中选择一些数(每个数可使用任意多次),用这些数组成一个长度为n的数列,并且满足任意两个不同种类的数都相邻。问最大的费用是多少。

m<=1e5,n<=2e6

题解

关键在于确定:使数列中有k个不同的数,数列的最小长度是多少。由于任意两个不同种类的数都相邻,联想到完全图的欧拉回路,即走过多少条边可以使每条边都经过一次,显然次数+1就是最小长度。有奇数个点的时候可以一笔画,只需(k-1)*k/2次即可,如果是偶数则需要额外的(k-2)/2次。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;

int n,m,val[N];

int check(int mid) {
	int x=mid*(mid-1)/2;
	if (mid%2==0) x+=(mid-2)/2;
	return n>=x+1;
}

signed main() {
	cin>>n>>m;
	for (int i=1;i<=m;i++) {
		int x,y; cin>>x>>y;
		val[i]=y;
	}
	sort(val+1,val+m+1);
	int l=1,r=m;
	while (l<r) {
		int mid=(l+r+1)>>1;
		if (check(mid)) l=mid;
		else r=mid-1;
	}
	int ans=0;
	for (int i=1;i<=l;i++) ans+=val[m-i+1];
	cout<<ans;
	return 0;
}