zoukankan      html  css  js  c++  java
  • 【BZOJ2151】种树(贪心)

    【BZOJ2151】种树(贪心)

    题面

    BZOJ

    题解

    如果没有相邻不能选的限制,那么这就是一道傻逼题。
    只需要用一个堆维护一下就好了。
    现在加上了相邻点的限制,那么我们就对于当前位置加入一个撤销操作。
    怎么撤销呢?
    如果我们选择了一个点,那么我们就把他前后两个位置删去,
    然后将当前点合并为(a[last]+a[next]-a[now])的权值。
    如果下次选择了这个位置的话,就可以认为撤销了选择(now)这个位置,
    转而选择了相邻的两个位置。
    用一个链表维护前驱后继,堆维护答案即可。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define pr pair<int,int>
    #define mp(x,y) (make_pair(x,y))
    #define MAX 200200
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    int nt[MAX],lt[MAX],n,m,a[MAX],ans;
    priority_queue<pr> Q;
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	for(int i=1;i<n;++i)nt[i]=i+1;nt[n]=1;
    	for(int i=2;i<=n;++i)lt[i]=i-1;lt[1]=n;
    	for(int i=1;i<=n;++i)Q.push(mp(a[i],i));
    	if(m>n/2){puts("Error!");return 0;}
    	while(m)
    	{
    		pr u=Q.top();Q.pop();
    		int v=u.second;
    		if(nt[lt[v]]!=v)continue;
    		a[v]=a[lt[v]]+a[nt[v]]-a[v];
    		lt[v]=lt[lt[v]];nt[v]=nt[nt[v]];
    		nt[lt[v]]=v;lt[nt[v]]=v;
    		Q.push(mp(a[v],v));ans+=u.first;
    		--m;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    19.02.11——周记
    假期第一周
    JavaWeb——升级赛-学生成绩管理系统(2).java---19.01.03
    JavaWeb——升级赛-学生成绩管理系统(1)jsp---19.01.03
    构建之法阅读笔记02
    输出一个数组里最大子数组的和(文件)
    软件工程第二周总结
    软件工程第一周开课博客
    构建之法阅读笔记01
    返回一个整数数组中最大子数组的和
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9367948.html
Copyright © 2011-2022 走看看