• [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]);
    }
    
  • 相关阅读:
    jenkins as code 与go语言学习
    VC++ 网络编程总结(一)
    Linux下的C高级编程---学习
    面试前必做4准备
    MFC视图切换大全总结
    多线程编程技术学---学习笔记--线程编程基础知识
    C语言高效编程的几招(绝对实用,绝对经典)
    汇编语言(学习笔记-----[bx]和loop)
    汇编语言(学习笔记----源程序)
    汇编语言(学习笔记----寄存器-内存访问)
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/14327605.html
Copyright © 2020-2023  润新知