zoukankan      html  css  js  c++  java
  • 领导集团问题「FJOI2018」

    【题目描述】 一个公司的组织领导架构可以用一棵领导树来表示。公司的每个成员对应于树中一个结点$v_i$,且每个成员都有响应的级别$w_i$。越高层的领导,其级别值$w_i$越小。树中任何两个结点之间有边相连,则表示与结点相应的两个成员属于同一部门。领导集团问题就是根据公司的领导树确定公司的最大部门。换句话说,也就是在领导树中寻找最大的部门结点子集,使得的结点$v_i$和$v_j$,如果$v_i$是$v_j$的子孙结点,则$w_i ge w_j$。 编程任务:对于任意对于给定的领导树,计算出领导树中最大的部门结点子集。

    【输入格式】 第一行有一个正整数$n$,表示领导树的结点数。接下来的一行中有$n$个整数。第$i$个数表示$w_i$。再接下来的$n - 1$行中,第$i$行有一个整数$v_i$表示$v_i$是$i + 1$的双亲结点。 (n) 为正整数,(n le 200000),$0 < w_i le 10^9$

    【输出格式】 输出找到的最大的部门的成员数。

    这题目描述故弄玄虚。。。害我看半天 简单来说就是选出树上一个点集(不一定要相连的点) 满足点集中任意两点$i,j$,如果$i$是$j$的直接祖先,一定有$w_ile w_j$。

    题解

    设计一个DP方程 $dp[i][j]$表示 在$i$的子树中(这棵树是有根树!),选择的所有点的权值全部大于等于$j$时 最多选多少个点。

    如果要选当前节点$u$ 那么在子树里选的点的权值就必须全部$ge w_u$ 所以转移方程十分显然(并不),如下:

    由于$u$的两个不同儿子的子树中怎么选点是互不影响的 所以在转移到$u$之前我们先把$u$所有儿子的$dp[v][j]$对应的加在一起(就是对于每一个$j$ 把所有儿子的$dp[?][j]$累加起来)

    我们再看看$dp[i][j]$的定义 容易发现对于一个点$x$ 随着$j$的增大 $dp[x][j]$肯定是不断减小的

    所以转移方程直接写成$dp[u][j]=dp[v][j]+ riangle$

    这个$ riangle$是什么?意思是说如果可以取$u$这个点 那么就是$1$ 否则为$0$

    关于能不能取$u$这个点其实不太好考虑 为什么不好考虑呢?首先 如果你取了$u$ 那么一定要$jle w_u$ 其次 如果$jle w_u$ 那么有可能$dp[v][j]$里面已经取了权值小于$w_u$的点了!所以我们先放在一边 稍后再来考虑

    把所有儿子的$dp$值累加总时间是$O(n^2)$的 这就不太行

    发现转移是在树上的 我们可以用线段树合并来操作这个DP转移 具体地说 线段树的每一个叶子的位置上存着$dp[i][j]$

    对于儿子的$dp$值累加 直接把所有儿子的线段树合并就行了

    然后关于那个$ riangle$ 肯定是有一段$dp[u][jsim k]$需要加$1$ 但是线段树合并不支持区间修改

    因为我们刚才提到的那个 “随着$j$的增大 $dp[x][j]$肯定是不断减小的” 的性质 我们可以让叶子节点存$dp$值的后缀差分数组 这样每次只用改两个点了

    到底哪一段要$+1$?后缀差分数组的第$w_u$项肯定是要$+1$的 然后$-1$的位置则是在 从后缀差分数组$w_u$项往前找第一个大于$0$的位置

    如果那个位置大于零了 就意味着在$u$的子树里已经取了一个权值小于$w_u$的点了(请自行理解)

    这个位置可以用线段树上二分找到(但是这个二分会显得比较抽搐 蒟蒻调半天调不出来只好去参考标程)

    答案就是最终的$dp[1][1]$ 也就是你把$1$号节点那个差分线段树整个加起来

    时间复杂度$O(nlog n)$

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    int n, w[200005], srt[200005], mx, ans;
    int head[200005], pre[400005], to[400005], sz; 
    bool ok;
    
    inline void addedge(int u, int v) {
    	pre[++sz] = head[u]; head[u] = sz; to[sz] = v;
    	pre[++sz] = head[v]; head[v] = sz; to[sz] = u;
    }
    
    struct tree{
    	int lc, rc, cnt;
    } tr[4000005];
    int rt[200005], tot;
    
    #define lson tr[ind].lc
    #define rson tr[ind].rc
    
    int merge(int x, int y) {
    	if (!x) return y;
    	if (!y) return x;
    	tr[x].lc = merge(tr[x].lc, tr[y].lc);
    	tr[x].rc = merge(tr[x].rc, tr[y].rc);
    	tr[x].cnt += tr[y].cnt;
    	return x;
    }
    
    void update(int &ind, int l, int r, int pos, int v) {
    	if (!ind) ind = ++tot;
    	tr[ind].cnt += v;
    	if (l == r) return;
    	int mid = (l + r) >> 1;
    	if (pos <= mid) update(lson, l, mid, pos, v);
    	else update(rson, mid+1, r, pos, v);
    }
    
    void del(int ind) { //这个还是二分
    	tr[ind].cnt--;
    	if (tr[rson].cnt) del(rson);
    	else if (tr[lson].cnt) del(lson);
    }
    
    void del(int ind, int l, int r, int pos) { //线段树上二分
    	if (l == r) return;
    	int mid = (l + r) >> 1;
    	if (pos <= mid) {
    		del(lson, l, mid, pos);
    	} else {
    		del(rson, mid + 1, r, pos);
    		if (!ok && tr[lson].cnt) {
    			del(lson);
    			ok = 1;
    		}
    	}
    	if (ok) tr[ind].cnt--;
    } 
    
    void dfs(int x, int fa) {
    	for (int i = head[x]; i; i = pre[i]) {
    		if (to[i] == fa) continue;
    		dfs(to[i], x);
    		rt[x] = merge(rt[x], rt[to[i]]);
    	}
    	update(rt[x], 1, n, w[x], 1);
    	ok = 0;
    	del(rt[x], 1, n, w[x]);
    }
    
    int main() {
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++) scanf("%d", &w[i]), srt[i] = w[i];
    	sort(srt + 1, srt + n + 1); 
    	mx = unique(srt + 1, srt + n + 1) - srt - 1;
    	for (int i = 1; i <= n; i++) w[i] = lower_bound(srt + 1, srt + mx + 1, w[i]) - srt;
    	for (int i = 2, fa; i <= n; i++) {
    		scanf("%d", &fa);
    		addedge(fa, i);
    	}
    	dfs(1, 0);
    	printf("%d
    ", tr[rt[1]].cnt);
    	return 0;
    } 
    
  • 相关阅读:
    mysql整理-常用sql语句
    WAMP中的mysql设置密码
    cmd中输入net start mysql 提示:服务名无效或者MySQL正在启动 MySQL无法启动
    “laravel.log” could not be opened: failed to open stream
    RESTful API 设计指南
    理解RESTful架构
    PHP:API 接口规范完整版本
    php的api接口
    laravel5.5部署
    《面向对象程序设计》课程作业二
  • 原文地址:https://www.cnblogs.com/ak-dream/p/AK_DREAM64.html
Copyright © 2011-2022 走看看