转载注明出处 http://blog.youkuaiyun.com/moedane
传送门 http://codeforces.com/contest/368/problem/E
题意
我们要用m个数,来构造一个长度为n的数组,要求数组有以下性质
consider all pairs of numbers x, y (x ≠ y), such that number x occurs in the array a and number y occurs in the array a;
for each pair x, y must exist some position j (1 ≤ j < n), such that at least one of the two conditions are met, either aj = x, aj + 1 = y, or aj = y, aj + 1 = x.
(偷懒直接复制原题中的英文╮( ̄▽ ̄”)╭)
给出的m个数各不相同,且各有一个价值w。
问构造这样的数组最多花费多少钱。
思路
其实就是要求数组中每一个数都必须跟其他任意一个数至少相邻一次。
只要满足这个条件,那么就尽可能地取更多的数即可。
于是问题就转化为,长度为n的数组最多能容纳多少个不同的数(满足上述条件的)。
然后从大到小贪心地取便是最大的。
至于怎么求长度为n的数组最多能容纳的数字的数目呢?
我手动列了一下:
1 ①
12 ②
1231 ③
12314234 ④
1231425351 ⑤
12314253516236456 ⑥
......
然后就可以发现一些规律:
在④中,数字2和3相邻了两次,所以要插入数字5的时候,大可将5放到其中一个23相邻的位置里。
由⑤到⑥,由于⑤中没有多余的位置可以插入,所以只能在后面加(如果在前面插入,则破坏了原来它满足条件的状态,这就需要在后面补回,这样做不会更优)。加的方法则如例子中,不可避免地会让一些数字重复相邻两遍……
于是就能总结出一个递推式:
if(i&1) f[i] = f[i-1] + (i-2)/2 + 2;
else f[i] = f[i-1] + (i-2) + ((i-2)/2 + 1);
(我这个递推式可能看上去有点抽象,大家大可以从上面的规律中自己推出递推式。)
这里的f[i] = k就表示要容纳i个不同的数字至少需要k的长度。
得出了这个,输入n时二分查找一下即可知道最多容纳多少个不同的数字。然后就直接取即可。
代码
#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <cctype>
#define bug puts("here");
using namespace std;
typedef long long ll;
const int maxn = 2 * 1000086;
const int mod = 1000000007;
const double PI = atan(1.0)*4.0;
int f[100086];
struct Node
{
int p,w;
}q[100086];
bool cmp(Node a,Node b)
{
return a.w > b.w;
}
int init()
{
f[0] = 0;
f[1] = 1;
f[2] = 2;
int i;
for(i=3;f[i-1] < maxn;i++)
{
if(i&1)
f[i] = f[i-1] + (i-2)/2 + 2;
else
f[i] = f[i-1] + (i-2) + ((i-2)/2 + 1);
}
return i;
}
int main()
{
int num = init();
int n,m;
scanf("%d%d",&n,&m);
int l = 1;
int r = num;
while(l<r-1)
{
int mid = l + (r-l)/2;
if(f[mid] == n)
{
l = mid;
break;
}
if(f[mid] < n) l = mid;
else r = mid;
}
int i;
for(i=0;i<m;i++)
scanf("%d%d",&q[i].p,&q[i].w);
sort(q,q+m,cmp);
int ans = 0;
for(i=0;i<l && i<m;i++)
{
ans += q[i].w;
}
printf("%d\n",ans);
return 0;
}