zoukankan      html  css  js  c++  java
  • 【洛谷P1484】种树【堆】【贪心】

    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P1484
    nn个点,选择其中互不相邻的不超过mm个点,使得点权和最大。


    思路:

    思维题。
    考虑贪心。如果我们第一次选择了最大值点ii,那么选择两个点时,要么点i1i-1和点i+1i+1一起选,要么两个都不选。

    如果我们选择点i1i-1和点x(xi+1)x(x≠i+1),那么贪心思想,a[i1]+a[x]a[i-1]+a[x]必然大于任意a[q]+a[p]a[q]+a[p]。但是当p=i,q=xp=i,q=x时,a[i>1]+a[x]a[i-> 1]+a[x]肯定小于a[i]+a[x]a[i]+a[x](因为一开始a[i]a[i]是最大的)。矛盾。
    证毕

    如果不选择a[i1]a[i-1]a[i+1]a[i+1],那么就是一个正常的贪心。但是如果选择a[i1]a[i-1]a[i+1]a[i+1]的话,就需要满足可撤销。
    如果我们把a[i]a[i]的值更改成a[i1]+a[i+1]a[i]a[i-1]+a[i+1]-a[i],再次选择aa数组中最大值,那么ansans就等于a[i]+a[i1]+a[i+1]a[i]=a[i1]+a[i+1]a[i]+a[i-1]+a[i+1]-a[i]=a[i-1]+a[i+1]

    这样用堆维护最大值,就可以做到O(mlogn)O(mlog n)的复杂度


    代码:

    #include <queue>
    #include <cstdio>
    #define mp make_pair
    using namespace std;
    typedef long long ll;
    
    const int N=500010;
    int n,m;
    bool p[N];
    ll a[N],ans;
    priority_queue<pair<ll,int> > q;
    
    struct node
    {
    	int l,r;
    }link[N];
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%lld",&a[i]);
    		q.push(mp(a[i],i));
    		link[i].l=i-1; link[i].r=i+1;
    	}
    	while (m--)
    	{
    		while (p[q.top().second]) q.pop();
    		if (q.top().first<0) break;
    		ans+=q.top().first;
    		int id=q.top().second;
    		a[id]=a[link[id].l]+a[link[id].r]-a[id];
    		p[link[id].l]=p[link[id].r]=1;
    		link[id].l=link[link[id].l].l; link[link[id].l].r=id;
    		link[id].r=link[link[id].r].r; link[link[id].r].l=id;
    		q.pop(); q.push(mp(a[id],id));
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    需求分析模板
    【转】卓有成效的敏捷开发流程
    敏捷建模者的个性
    四个凡事:有章可循,有人负责,有据可查,有人监督
    全局变量初始化的重要性
    Windows下虚拟串口工具:com0com可做串口调试用
    【转】各种加解密算法比较
    WSASocket函数未定义和重定义错误
    海明校验码
    stl学习总结
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998151.html
Copyright © 2011-2022 走看看