[BZOJ3829][Poi2014]FarmCraft 贪心
Posted TS_Hugh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ3829][Poi2014]FarmCraft 贪心相关的知识,希望对你有一定的参考价值。
这个题应该是很容易想到贪心的,只要可是怎么贪才是科学的呢?
我们分析一下题干,对于每个边只能一进一出因此,对于树上的一棵子树,我们只要一进子树就必须遍历完,
因此我们只能进行一遍 dfs() 然后我们发现 dfs() 一遍的时间是一定的,
然后见每个妹子的时间就在这个时间轴上,
分析完了,我们说一下要贪什么。
我们先定义一个概念rest[]就是遍历完这个节点的子树以后我们还要为这个节点所费的时间
One_Stage :除了1节点,之外每个妹子一见面就杀du
Two_Stage :我们发现最后的答案是 Max(rest[1],c[1])+2*n-2
Three_Stage :然后我们考虑怎么找rest[1],
我们发现每个节点的最优rest[],是(子节点的rest[],减去其在这个子树里又经过的时间),再和(他的c[]减去遍历他的时间)取Max
这样我们线性一波就结局了
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define MAXN 500005 using namespace std; inline int read() { register int sum=0; register char ch=getchar(); while(ch<‘0‘||ch>‘9‘)ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) { sum=(sum<<1)+(sum<<3)+ch-‘0‘; ch=getchar(); } return sum; } inline int Max(int x,int y) { return x>y?x:y; } int a[MAXN],m[MAXN],n,t[MAXN]; vector<int> Via[MAXN]; void Dfs_T(int x,int fa) { register int len=Via[x].size(); for(register int i=0;i<len;++i) if(Via[x][i]!=fa) { Dfs_T(Via[x][i],x); t[x]+=2+t[Via[x][i]]; } } inline void Init() { n=read(); for(register int i=1;i<=n;i++)a[i]=read(); for(register int i=1,x,y;i<n;i++)x=read(),y=read(),Via[x].push_back(y),Via[y].push_back(x); Dfs_T(1,0); } int rest[MAXN]; int comp(const int x,const int y) { return rest[x]>rest[y]; } inline void Dfs_A(int x,int fa) { register int len=Via[x].size(); for(register int i=0;i<len;++i) if(Via[x][i]!=fa)Dfs_A(Via[x][i],x); sort(Via[x].begin(),Via[x].end(),comp); if(x!=1)rest[x]=a[x]-t[x]; register int now=t[x]; for(register int i=0;i<len;i++) if(Via[x][i]!=fa) { now-=2+t[Via[x][i]]; rest[x]=Max(rest[x],rest[Via[x][i]]-now-1); } if(rest[x]<0)rest[x]=0; } inline void Work() { Dfs_A(1,0); register int ans=Max(rest[1],a[1])+t[1]; printf("%d",ans); } int main() { Init(); Work(); return 0; }
以上是关于[BZOJ3829][Poi2014]FarmCraft 贪心的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ2223][BZOJ3524][Poi2014]Couriers 主席树
BZOJ3831[Poi2014]Little Bird 单调队列