您的位置:首页 > 其它

bzoj2151 种树

2017-01-22 21:10 375 查看
【题意】

n个数构成环,取出m个数,满足取出的任意两个数不相邻,求最大和

【数据范围】

n<=200000

【思路】

方法同bzoj1150,使用可放回的贪心

【时间复杂度】

O(n log n)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define N 200010
#define pa(a, b) (data){a, b}
using namespace std;
struct data{int x, id;}t;
bool operator<(data a, data b){
if(a.x!=b.x)return a.x<b.x;
return a.id<b.id;
}
struct heap{
priority_queue<data, vector<data>, less<data> >A, B;
void ins(int x, int id){A.push(pa(x, id));}
void del(int x, int id){B.push(pa(x, id));}
data top(){
data t1, t2;
while(!B.empty()){
t1=A.top(); t2=B.top();
if(t1.x==t2.x&&t1.id==t2.id){A.pop(); B.pop();} else break;
}
return A.top();
}
}q;
int n, m, w
, pre
, next
, ans;
inline int read(){
int x=0, f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int main(){
n=read(); m=read();
for(int i=1; i<=n; i++)w[i]=read();
if(m>n/2){printf("Error!"); return 0;}
for(int i=1; i<=n; i++){
pre[i]=i-1; next[i]=i+1;
if(i==1)pre[i]=n; if(i==n)next[i]=1;
q.ins(w[i], i);
}
ans=0;
for(int i=1; i<=m; i++){
t=q.top(); ans+=t.x; q.del(t.x, t.id);
w[t.id]=w[pre[t.id]]+w[next[t.id]]-w[t.id]; q.ins(w[t.id], t.id);
q.del(w[pre[t.id]], pre[t.id]); q.del(w[next[t.id]], next[t.id]);
pre[t.id]=pre[pre[t.id]]; next[pre[t.id]]=t.id;
next[t.id]=next[next[t.id]]; pre[next[t.id]]=t.id;
}
printf("%d", ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: