zoukankan      html  css  js  c++  java
  • [FJOI2018]领导集团问题

    https://www.luogu.org/problemnew/show/P4577

    题解

    我们可以先搞一个(dp)出来,(dp[u][i])表示以(u)号节点为根的子树,选择集合元素中最小的不小于(i)的最优方案。

    然后我们可以发现这个(dp)是自带一个后缀(max)的,然后我们把它向后差分一下去维护。

    那么观察到对于一个节点,它的所有子树之间是互不影响的,所以我们直接把他们对应位置加起来就好了。

    然后考虑加入当前的根节点,发现这个(dp)值会有一段区间(+1),直接在差分数组上维护就好了。

    (set)维护差分数组的拐点超级好写。。。

    代码

    #include<bits/stdc++.h>
    #define N 200009
    using namespace std;
    typedef long long ll;
    int head[N],tot,n,w[N];
    multiset<int>s[N];
    multiset<int>::iterator it;
    inline ll rd(){
    	ll x=0;char c=getchar();bool f=0;
    	while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f?-x:x;
    }
    struct edge{int n,to;}e[N];
    inline void add(int u,int v){
    	e[++tot].n=head[u];e[tot].to=v;head[u]=tot;
    }
    inline void merge(multiset<int> &u,multiset<int> &v){
    	if(u.size()<v.size())swap(u,v);
    	for(it=v.begin();it!=v.end();++it)u.insert(*it);
    }
    void dfs(int u){
    	for(int i=head[u];i;i=e[i].n){
    		int v=e[i].to;
    	    dfs(v);
    	    merge(s[u],s[v]);
    	    s[v].clear();
    	}
    	s[u].insert(w[u]);
    	it=s[u].lower_bound(w[u]);
    	if(it!=s[u].begin())--it,s[u].erase(it);
    } 
    int main(){
    	n=rd();
    	for(int i=1;i<=n;++i)w[i]=rd();
    	for(int i=2;i<=n;++i){
    		int x=rd();
    		add(x,i);
    	} 
    	dfs(1);
    	printf("%d",s[1].size());
    	return 0;
    }
    
  • 相关阅读:
    sgg_3_hibernate详解
    sgg_2_hibernate开发步骤
    sgg_1_hibernate概述
    cookie
    exchange 普通用户可以创建通讯组
    DC 维护常用工具命令DCdiag
    cp 复制不覆盖
    powershell 结果输出显示为……
    获得用户完整的autodiscover配置文件
    【转】outlook 2016 配置自动发现
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10799049.html
Copyright © 2011-2022 走看看