BZOJ 4756 [Usaco2017 Jan]Promotion Counting dfs序+主席树

2024-03-30 16:48

本文主要是介绍BZOJ 4756 [Usaco2017 Jan]Promotion Counting dfs序+主席树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

The cows have once again tried to form a startup company, failing to remember from past experience t
hat cows make terrible managers!The cows, conveniently numbered 1…N1…N (1≤N≤100,000), organize t
he company as a tree, with cow 1 as the president (the root of the tree). Each cow except the presid
ent has a single manager (its "parent" in the tree). Each cow ii has a distinct proficiency rating, 
p(i), which describes how good she is at her job. If cow ii is an ancestor (e.g., a manager of a man
ager of a manager) of cow jj, then we say jj is a subordinate of ii.
Unfortunately, the cows find that it is often the case that a manager has less proficiency than seve
ral of her subordinates, in which case the manager should consider promoting some of her subordinate
s. Your task is to help the cows figure out when this is happening. For each cow ii in the company, 
please count the number of subordinates jj where p(j)>p(i).
n只奶牛构成了一个树形的公司,每个奶牛有一个能力值pi,1号奶牛为树根。
问对于每个奶牛来说,它的子树中有几个能力值比它大的。

Input

The first line of input contains N
The next N lines of input contain the proficiency ratings p(1)…p(N) 
for the cows. Each is a distinct integer in the range 1…1,000,000,000
The next N-1 lines describe the manager (parent) for cows 2…N 
Recall that cow 1 has no manager, being the president.
n,表示有几只奶牛 n<=100000
接下来n行为1-n号奶牛的能力值pi
接下来n-1行为2-n号奶牛的经理(树中的父亲)

Output

Please print N lines of output. The ith line of output should tell the number of 
subordinates of cow ii with higher proficiency than cow i.
共n行,每行输出奶牛i的下属中有几个能力值比i大

Sample Input

5
804289384
846930887
681692778
714636916
957747794
1
1
2
3

Sample Output

2
0
1
0
0

HINT





传送门
有一个比较简单的想法,就是维护权值的线段树,然后根据dfs序求出即可。
问题就是不同子树,
当然有很多做法,比如线段树合并。
但是本菜只会主席树……那就刚一发主席树。

一开始一直查不到错……后来发现root的标号竟然打错了。。zz。。
其实主席树这东西,我也不知道叫chairtree,还是chairmantree,还是都可。。
好吧总算A了一题……



#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int n,Ecnt,Tcnt,cnt;
int a[N],ANS[N],root[N];struct node{int x,id;}p[N];
bool cmp(node a,node b){return a.x<b.x;}
struct ChairTree{int l,r,num;}ct[N*18];
struct Tree{int tid,MAX;}tree[N];
struct Edge{int next,to;}E[N<<1];int head[N];void add(int u,int v){E[++Ecnt].next=head[u];E[Ecnt].to=v;head[u]=Ecnt;
}
void insert(int L,int R,int &x,int g){ct[++Tcnt]=ct[x];x=Tcnt;ct[x].num++;if (L==R) return;int mid=(L+R)>>1;if (g<=mid) insert(L,mid,ct[x].l,g);else insert(mid+1,R,ct[x].r,g);
}
int query(int L,int R,int x,int y,int gl,int gr){if (L>=gl && R<=gr) return ct[y].num-ct[x].num;int mid=(L+R)>>1,t=0;if (gl<=mid) t+=query(L,mid,ct[x].l,ct[y].l,gl,gr);if (gr>mid) t+=query(mid+1,R,ct[x].r,ct[y].r,gl,gr);return t;
}
void ins(int x){root[tree[x].tid]=root[tree[x].tid-1];insert(1,n,root[tree[x].tid],a[x]);
}
void dfs(int u,int pre){tree[u].tid=++cnt;ins(u);tree[u].MAX=tree[u].tid;for (int i=head[u];i;i=E[i].next){int v=E[i].to;if (v==pre) continue;dfs(v,u);tree[u].MAX=max(tree[u].MAX,tree[v].MAX);}ANS[u]=query(1,n,root[tree[u].tid-1],root[tree[u].MAX],a[u]+1,n);
}
int main(){scanf("%d",&n);for (int i=1;i<=n;i++)scanf("%d",&p[i]),p[i].id=i;sort(p+1,p+1+n,cmp);for (int i=1;i<=n;i++)if (p[i].x==p[i-1].x) a[p[i].id]=a[p[i-1].id];else a[p[i].id]=i;int x;Ecnt=0;for (int i=2;i<=n;i++)scanf("%d",&x),add(x,i),add(i,x);root[0]=Tcnt=cnt=0;dfs(1,0);for (int i=1;i<=n;i++) printf("%d\n",ANS[i]);return 0;
}

这篇关于BZOJ 4756 [Usaco2017 Jan]Promotion Counting dfs序+主席树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/862036

相关文章

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

ural 1149. Sinus Dances dfs

1149. Sinus Dances Time limit: 1.0 second Memory limit: 64 MB Let  An = sin(1–sin(2+sin(3–sin(4+…sin( n))…) Let  Sn = (…( A 1+ n) A 2+ n–1) A 3+…+2) An+1 For given  N print  SN Input One

hdu 6198 dfs枚举找规律+矩阵乘法

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description We define a sequence  F : ⋅   F0=0,F1=1 ; ⋅   Fn=Fn

深度优先(DFS)和广度优先(BFS)——算法

深度优先 深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支,当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访

nyoj99(并查集+欧拉路+dfs)

单词拼接 时间限制: 3000 ms  |  内存限制: 65535 KB 难度: 5 描述 给你一些单词,请你判断能否把它们首尾串起来串成一串。 前一个单词的结尾应该与下一个单词的道字母相同。 如 aloha dog arachnid gopher tiger rat   可以拼接成:aloha.arachnid.dog.gopher.rat.tiger 输入 第一行是一个整

【CF】E. Anya and Cubes(双向DFS)

根据题意的话每次递归分3种情况 一共最多25个数,时间复杂度为3^25,太大了 我们可以分2次求解第一次求一半的结果,也就是25/2 = 12,记录结果 之后利用剩余的一半求结果 s-结果 = 之前记录过的结果 就可以 时间复杂度降低为 3 ^ (n/2+1) 题目链接:http://codeforces.com/contest/525/problem/E #include<set

力扣 797. 所有可能路径【DFS】

1. 题目 2. 代码 DFS , 直接见代码 class Solution {public:vector<int> path;vector<vector<int>> res; // 结果集void dfs(vector<vector<int>>& graph, int cur, int n){// 找出所有从节点 0 到节点 n-1 的路径// 下标从 0 开始的if (

CF Bayan 2015 Contest Warm Up B.(dfs+暴力)

B. Strongly Connected City time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output 题目链接: http://codeforces.com/contest/475/probl

POJ 2386 Lake Counting(DFS)

题目: http://poj.org/problem?id=2386 题解: 遍历一次,遇到w,一次DFS后,与此w连接的所有w都被替换成‘ . ’,直到遍历完图中不再存在w为止,总共进行DFS的次数就是答案了。 代码: #include<stdio.h>int N,M;char map[110][110];void dfs(int x,int y){map[x][y]='