猫
(cat)
【问题描述】
信息组最近猫成灾了
!
隔壁物理组也拿猫没办法
.
信息组组长只好去请神刀手
来帮他们消灭猫
.
信息组现在共有
n
只猫
(n
为正整数
),
编号为
1
到
n,
站成了一个环
,
第
i
只猫的
左边是第
i-1
只猫
,
右边是第
i+1
只猫
.
特别的
,
第
1
只猫的左边是第
n
只猫
,
第
n
只
猫的右边是第
1
只猫
.
每只猫拥有价值
,
表示消灭它能给信息组组长带来的声誉
.
注意
,
有的猫价值为负数
,
这意味着消灭它会损害组长的声誉
.
神刀手可以选择一些猫消灭掉
.
但是
,
我们的组长实际上非常喜欢猫
,
他希望神
刀手不要消灭两只相邻的猫
.
神刀手的能力组长现在还不知道
.
所以
,
组长希望知道对于所有的
1<=m<=n/2,
如果神刀手刚好消灭
m
只猫
,
他最多能获得的声誉
.
信息组组长当然知道怎么做啦!但是他想考考你……
【输入格式】
从
cat.in
中读入数据
第一行包括一个正整数
n
第二行为
n
个整数
,
依次代表第
1,2,...,n
只猫的价值
.
【输出格式】
输出到文件
cat.out
输出共
n/2
行
,
第
i
行表示假如神刀手刚好消灭
i
只猫
,
信息组组长最多能获得
的收益
.
【样例输入
1
】
8
1 1 8 1 1 9 1 1
【样例输出
1
】
9
17
18
12
【样例输入
2
】
11
5 6 7 8 9 10 9 8 7 6 5
【样例输出
2
】
10
18
26
32
38
【数据规模与约定】
对于
30%
的数据
,
满足
n<=20
对于
60%
的数据
,
满足
n<=2000
对于另外
20%
的数据
,
满足
n
为偶数
对于
100%
的数据
,
满足
1<=n<=200000,|
每只猫的价值
|<=1e9
说实话,这题有点意思。
后悔贪心的模板题;
优先队列STL维护堆;
重载结构体运算符。
后悔贪心主要思路就是:贪心取出最大值b后,只是局部最优解,若要整体最优解,需要将两边的a,c压缩一下,也就是将b的值变为a+c-b,这样再取一次值,就相当于取了a,c,链表维护也行。
上代码:
#include<bits/stdc++.h>
using namespace std;
struct node
{
int pos;
long long val;
};
bool operator < (const node &a,const node &b)
{
return a.val<b.val;
}
priority_queue<node> que;
int n,lat[400010],nxt[400010],vis[400010];
long long value[400010];
int main()
{
scanf("%d",&n);
for(register int i=1;i<=n;i++)
{
scanf("%lld",&value[i]);
}
for(register int i=1;i<=n;i++)
{
if(i==1) lat[i]=n;
else lat[i]=i-1;
if(i==n) nxt[i]=1;
else nxt[i]=i+1;
que.push((node){i,value[i]});
}
int m=n/2,k=n;
long long answer=0;
while(m--)
{
node now=que.top();
que.pop();
while(!que.empty()&&vis[now.pos])
{
now=que.top();
que.pop();
}
vis[now.pos]=vis[lat[now.pos]]=vis[nxt[now.pos]]=1;
answer+=now.val;
printf("%lld\n",answer);
value[++k]=value[lat[now.pos]]+value[nxt[now.pos]]-value[now.pos];
lat[k]=lat[lat[now.pos]],nxt[lat[lat[now.pos]]]=k;
nxt[k]=nxt[nxt[now.pos]],lat[nxt[nxt[now.pos]]]=k;
que.push((node){k,value[k]});
}
}