zoukankan      html  css  js  c++  java
  • LG1484 种树

    题意

    (N)个数,至多选(k)个,相邻两数不能同时选,问最大价值。

    思路

    一种假的思路:直接扔进对里面,每次都选最大的可以选的,再把两边和自己标记为不能选,一直贪心下去。是不是很有道理?
    假在哪里?虽然这个是最大的,旁边两个加起来比它大,就错了。
    把这个假贪心改一改,赐予它一个反悔的机会。如果它不选(i),那么它可以选则(last[i])(next[i]),这两个一定是一起选的(因为在一起才有超过(i)的可能)。此时它的价值为(a[last[i]]+a[next[i]]),原先已经选了(a[i]),所以就再扔一个(a[last[i]]+a[next[i]]-a[i]) 进去取代原来的数。由于这样选了(2)个数,而选一次反悔一次也恰好用掉(2)次机会,所以正好。
    置于维护(last、next)只要用双向链表就好了

    #include <bits/stdc++.h>
    using namespace std;
    pair<int,int> t;
    const int N=500005;
    int n,k,a[N],f[N],last[N],Next[N];
    long long ans;
    priority_queue <pair<int,int>> q;
    int main(){
    	scanf("%d%d",&n,&k);
    	for (int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		q.push(make_pair(a[i],i));
    	}
    	for (int i=1;i<=n;i++) last[i]=i-1,Next[i]=i+1;
    	last[n+1]=n,Next[0]=1;
    	for (int i=1;i<=k;i++){
    		t=q.top();
    		while (f[t.second]) q.pop(),t=q.top();
    		q.pop();
    		if (t.first<0) break;
    		ans+=t.first;
    		int id=t.second;
    		f[last[id]]=f[Next[id]]=1;
    		a[id]=a[last[id]]+a[Next[id]]-a[id];
    		q.push(make_pair(a[id],id));
    		last[id]=last[last[id]],Next[id]=Next[Next[id]];
    		Next[last[id]]=id,last[Next[id]]=id;
    	}
    	printf("%lld",ans);
    }
    
    * 生而自由 爱而无畏 *
  • 相关阅读:
    对其他组的评论与意见
    第一阶段结果展示
    团队第一阶段冲刺绩效评估
    团队冲刺第八天站立会议
    团队检查博客
    团队冲刺地七天站立会议
    团队冲刺第六天站立会议
    团队冲刺第五天战略站立会议
    团队冲刺第四天战略会议站立
    No2_2.接口继承多态_Java学习笔记_继承
  • 原文地址:https://www.cnblogs.com/flyfeather6/p/10632781.html
Copyright © 2011-2022 走看看