种树
题目地址
之前见过类似的题目(见《贪心》赵和旭课件),思路知道,不再赘述。
错因:(处理麻烦先不算)
假设现在有5个点,从左到右依次编号1,2,3,4,5。假设第一次选了3号点,后来“反悔”了一次,选了2号和4号。假设最终答案选1,3,5号最优。我自己的代码中反悔了一次就处理不到再反悔一次的情况。
错误的代码(10分):
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define LL long long
using namespace std;
const LL N = 500005;
struct node{
LL val,id,num;
bool friend operator < (const node& a,const node& b)
{
return a.val<b.val;
}
}a[N];
priority_queue<node> q;
LL n,k,ans,t,tmp,ansl;
bool book[N];
bool cmp(node a,node b)
{ return a.val>b.val; }
int main()
{
scanf("%lld%lld",&n,&k);
for(LL i=1;i<=n;i++)
{
scanf("%lld",&a[i].val);
a[i].id=i; a[i].num=(a[i-1].val+a[i+1].val-a[i].val);
// q.push(a[i]);
}
sort(a+1,a+n+1,cmp);
tmp=1;
for(LL i=1;i<=k;i++)
{
while(book[a[tmp].id]) ++tmp;
// cout<<ans<<"*"<<endl;
// if(max(q.top().val,a[tmp].val)<0) break;
if(q.empty()||(a[tmp].val>q.top().val))
{
book[a[tmp].id]=book[a[tmp].id-1]=1;
book[a[tmp].id+1]=1;
ans+=a[tmp].val;
ansl=max(ansl,ans);
// t=a[tmp].id;
node tt;
tt.val=a[tmp].num; tt.id=a[tmp].id-1;
++tmp;
q.push(tt);
}
else
{
ans+=q.top().val;
t=q.top().id;
ansl=max(ansl,ans);
q.pop();
book[t-1]=book[t+3]=1;
}
}
printf("%lld\n",ansl);
return 0;
}
AC代码(题解):
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define LL long long
using namespace std;
const LL N = 5e5+5;
struct node{
LL v,id;
bool friend operator <(const node& a,const node& b)
{ return a.v<b.v; }
}t;
priority_queue<node>Q;
LL a[N],ans,l[N],r[N],n,m;
bool ok[N];
int main()
{
scanf("%lld%lld",&n,&m);
for(LL i=1;i<=n;i++)
{
scanf("%lld",&t.v);
a[i]=t.v;
t.id=i;
l[i]=i-1;
r[i]=i+1;
Q.push(t);
}
r[0]=1; l[n+1]=n;
while(m--)
{
while(ok[Q.top().id]) Q.pop();
t=Q.top(); Q.pop();
if(t.v<0) break;
ans+=t.v;
LL x=t.id;
a[x]=a[l[x]]+a[r[x]]-a[x];
t.v=a[x];
ok[l[x]]=ok[r[x]]=1;
l[x]=l[l[x]]; r[l[x]]=x;
r[x]=r[r[x]]; l[r[x]]=x;
Q.push(t);
}
printf("%lld",ans);
return 0;
}