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

    前言

    巨佬说:要有线段树,结果蒟蒻打了一棵树状数组...
    想想啊,奶牛都开公司当老板了,我还在这里码代码,太失败了。
    话说奶牛开个公司老板不应该是FarmerJohn吗

    题解

    刚看到这道题的时候竟然没有想到深搜,然后仔细一想,发现果然要用深搜
    但是这个树形结构怎么维护是一个问题?难道打个欧拉序...
    其实做法非常简单,首先按照套路我们把牛的能力值离散化(由于没有相同的值,所以这个离散化非常简单)。
    然后重点来了,建立一个维护某一能力值牛的个数的树状数组
    我们深搜到一个点的时候,我们不希望计算的部分是比它大的祖先,而希望计算的部分是比它大的儿子。
    于是我们在搜到这个点的时候将它的答案减去当前树状数组里能力值比它大的牛的个数(减去祖先部分),然后我们搜索它的所有儿子。
    搜索完成后,我们将它的答案加上当前树状数组里比它大的牛的个数(加上儿子和祖先部分)。所以一加一减只剩下儿子的部分。
    然后输出我们的答案数组,就AC了。

    代码

    #include <cstdio>
    #include <algorithm>
    #define ll long long
    
    using namespace std;
    
    ll read(){
    	ll x = 0; int zf = 1; char ch = ' ';
    	while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    	if (ch == '-') zf = -1, ch = getchar();
    	while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
    }
    
    struct Edge{
    	int to, next;
    } edges[200005];
    
    int head[100005], edge_num = 0;
    
    void addEdge(int from, int to){
    	edges[++edge_num] = (Edge){to, head[from]};
    	head[from] = edge_num;
    }
    
    int n;
    
    namespace FenTree{
    	#define lowbit(x) (x&-x)
    	int BIT[100005];
    	int query(int i){
    		int res = 0;
    		for ( ; i; i -= lowbit(i)) res += BIT[i]; return res;
    	}
    	void add(int i){
    		for ( ; i <= n; i += lowbit(i)) ++BIT[i];
    	}
    	#undef lowbit
    };
    
    using namespace FenTree;
    
    int p[100005], dy[100005];
    int ans[100005];
    
    bool Comp(const int &a, const int &b){return p[a] > p[b];};
    
    void DFS(int u, int fa){
    	ans[u] -= query(p[u]);
    	for (int c_e = head[u]; c_e; c_e = edges[c_e].next)
    		if (edges[c_e].to != fa) DFS(edges[c_e].to, u);
    	ans[u] += query(p[u]); add(p[u]);
    }
    
    int main(){
    	n = read();
    	for (int i = 1; i <= n; ++i) p[i] = read(), dy[i] = i;
    	sort(dy + 1, dy + n + 1, Comp);
    	for (int i = 1; i <= n; ++i) p[dy[i]] = i;
    	for (int i = 2; i <= n; ++i){int x = read(); addEdge(i, x), addEdge(x, i);}
    	DFS(1, 1);
    	for (int i = 1; i <= n; ++i) printf("%d
    ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    【做题】51NOD1518 稳定多米诺覆盖——容斥&dp
    【做题】TCSRM592 Div1 500 LittleElephantAndPermutationDiv1——计数&dp
    【做题】TCSRM591 Div1 500 PyramidSequences——数形结合&思维
    【做题】NOWCODER142A Ternary String——数列&欧拉定理
    【做题】CF196E. Opening Portals 排除无用边&最小生成树
    【做题】HDU6331 Walking Plan——矩阵&分块
    【做题】BZOJ2534 L-gap字符串——调和级数
    【做题】BZOJ2342 双倍回文——马拉车&并查集
    overleaf 提交arXiv 不成功
    神经网络 (2)- Alexnet Training on MNIST
  • 原文地址:https://www.cnblogs.com/linzhengmin/p/11129275.html
Copyright © 2011-2022 走看看