Description
A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。
Input
输入的第一行包含两个正整数n、m。第二行n个整数Ai。
Output
输出一个整数,表示最佳植树方案可以得到的美观度。如果无解输出“Error!”,不包含引号。
Sample Input
【样例输入1】
7 3
1 2 3 4 5 6 7
【样例输入2】
7 4
1 2 3 4 5 6 7
Sample Output
【样例输出1】
15
【样例输出2】
Error!
HINT
【数据规模】
对于全部数据:m<=n;
-1000<=Ai<=1000
N的大小对于不同数据有所不同:
数据编号 N的大小 数据编号 N的大小
1 30 11 200
2 35 12 2007
3 40 13 2008
4 45 14 2009
5 50 15 2010
6 55 16 2011
7 60 17 2012
8 65 18 199999
9 200 19 199999
10 200 20 200000
题解
相似与bzoj1150,只不过这道题算是那道题的弱化版。。
因为给出的序列无需考虑边界问题2333
老做法,堆维护队列。记录一下这个点的权以及位置
当取出一个点的时候,加入一个新点进堆。新点的权为他左边那个点的权+右边那个点的权-取出点的权。如果取旁边两个比取当前这个更优的话,那么下一次就会取到新加入那个点了,同时维护了贪心。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
struct node
{
int c,u;
friend bool operator <(node n1,node n2){return n1.c<n2.c;}
};//值 位置
priority_queue<node> q;
int n,m,col[210000],pre[210000],nxt[210000],del[210000];
int sum[210000];
int main()
{
memset(del,0,sizeof(del));
scanf("%d%d",&n,&m);
if(n<m*2){printf("Error!\n");return 0;}
for(int i=1;i<=n;i++)scanf("%d",&col[i]),pre[i]=i-1,nxt[i]=i+1,sum[i]=col[i];
pre[1]=n;nxt[n]=1;
for(int i=1;i<=n;i++)
{
node tmp;
tmp.c=col[i];tmp.u=i;
q.push(tmp);
//printf("%d\n",q.top().c);
}
int ans=0;
for(int i=1;i<=m;i++)
{
node tmp=q.top();
while(del[tmp.u]!=0)q.pop(),tmp=q.top();
ans+=tmp.c;q.pop();
int l=pre[tmp.u],r=nxt[tmp.u],cnt=0;
//把前后一条删掉,加入最大值为suml+sumr-sumu的线段,位置为tmp.u
del[l]=1;cnt+=sum[l];
pre[tmp.u]=pre[l];nxt[pre[l]]=tmp.u;
del[r]=1;cnt+=sum[r];
nxt[tmp.u]=nxt[r];pre[nxt[r]]=tmp.u;
node P;
P.u=tmp.u;P.c=cnt-tmp.c;del[tmp.u]=0;
sum[P.u]=P.c;
q.push(P);
}
printf("%d\n",ans);
return 0;
}

本文介绍了一个关于在圆形广场种植树木的算法问题,旨在通过合理的布局获得最大的美观度总和。文章详细阐述了解决方案,包括如何使用优先队列维护可能的最佳选择,并确保满足题目条件。

被折叠的 条评论
为什么被折叠?



