51nod 夹克老爷的逢三抽一

Posted on 2016-02-23 21:05  ziliuziliu  阅读(287)  评论(0编辑  收藏  举报

思考了一下,想到了贪心的大致思路,但是再更深层的就没有想法了。
于是ziliuziliu看了一下题解。优先队列。不错嘛。。。。

最把周围两个数的和减去这个数重新加入队列中。精彩!为什么?

考虑如果我们两次都选这个位置上的数,也就是A,B,C,那么答案就增加了B+(C+A-B)=(A+C)!

这不恰好是我们想要的吗。如果选了这个数不是最优解,我们可以有一个反悔的机会。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 100005
using namespace std;
long long n,val[maxn],ans=0;
bool vis[maxn];
struct node
{
long long w,pos;
friend bool operator < (node x,node y)
{
return x.w<y.w;
}
};
priority_queue <node> q;
int main()
{
memset(vis,true,sizeof(vis));
scanf("%lld",&n);
for (long long i=0;i<n;i++)
{
scanf("%lld",&val[i]);
node now;
now.w=val[i];now.pos=i;
q.push(now);
}
long long cnt=0;
do
{
node now=q.top();
q.pop();
if (vis[now.pos]==true)
{
cnt++;
long long left=(now.pos-1+n)%n,right=(now.pos+1+n)%n;
while (vis[left]==false)
left=(left-1+n)%n;
while (vis[right]==false)
right=(right+1+n)%n;
vis[left]=false;vis[right]=false;
node then;
then.w=val[left]+val[right]-val[now.pos];
then.pos=now.pos;
q.push(then);
ans=ans+val[now.pos];
val[now.pos]=val[left]+val[right]-val[now.pos];
}
}while (cnt!=n/3);
printf("%lld\n",ans);
return 0;
}