zoukankan      html  css  js  c++  java
  • [USACO17JAN]Promotion Counting P

    题目大意

    大小为 (n)(1) 为根的树,点带权,求每个子树内大于本点的点的数量
    (1 le n le 10^5,1 le p_i le 10^9)

    题解

    一眼静态链分治,然后统计?
    离散化后树状数组维护即可
    时间复杂度 (n log ^2 (n))

    (Code)

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int N = 1e5 + 5;
    int n, h[N], tot;
    struct edge{int to, nxt;}e[N];
    inline void add(int x, int y){e[++tot] = edge{y, h[x]}, h[x] = tot;}
    struct node{int p, id;}a[N];
    inline bool cmp1(node x, node y){return x.p < y.p;}
    inline bool cmp2(node x, node y){return x.id < y.id;}
    
    int dfc, fa[N], siz[N], dfn[N], rev[N], son[N], ans[N];
    void dfs1(int x)
    {
    	siz[x] = 1, dfn[x] = ++dfc, rev[dfc] = x;
    	for(register int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		dfs1(v), siz[x] += siz[v];
    		if (siz[v] > siz[son[x]]) son[x] = v;
    	}
    }
    
    int c[N];
    inline int lowbit(int x){return x & (-x);}
    inline void update(int x, int v){for(; x <= n; x += lowbit(x)) c[x] += v;}
    inline int query(int x)
    {
    	int res = 0;
    	for(; x; x -= lowbit(x)) res += c[x];
    	return res;
    }
    
    void dfs2(int x, int kp)
    {
    	for(register int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		if (v == son[x]) continue;
    		dfs2(v, 0);
    	}
    	if (son[x]) dfs2(son[x], 1);
    	for(register int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		if (v == son[x]) {update(a[son[x]].p, 1); continue;}
    		for(register int j = dfn[v]; j <= dfn[v] + siz[v] - 1; j++) update(a[rev[j]].p, 1);
    	}
    	ans[x] = siz[x] - 1 - query(a[x].p);
    	if (!kp) for(register int i = dfn[x] + 1; i <= dfn[x] + siz[x] - 1; i++) update(a[rev[i]].p, -1);
    }
    
    int main()
    {
    	scanf("%d", &n);
    	for(register int i = 1; i <= n; i++) scanf("%d", &a[i].p), a[i].id = i;
    	sort(a + 1, a + n + 1, cmp1);
    	for(register int i = 1; i <= n; i++) a[i].p = i;
    	sort(a + 1, a + n + 1, cmp2);
    	for(register int i = 2; i <= n; i++) scanf("%d", &fa[i]), add(fa[i], i);
    	dfs1(1), dfs2(1, 1);
    	for(register int i = 1; i <= n; i++) printf("%d
    ", ans[i]);
    }
    
  • 相关阅读:
    个人冲刺计划一周天详细
    软件小创意
    电梯调度小程序。
    敏捷开发一些百科。
    求二维数组的子数组中的最大值!
    求整数数组中子数组最大的和值!
    单元测试我们应该注意什么!
    分析一个文档(英语文章)中各个词出现的频率,并打印频率最高的前10个。
    有感而发
    冲刺一TD美景美图
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/14327605.html
Copyright © 2011-2022 走看看