zoukankan      html  css  js  c++  java
  • CSU-2172 买一送一

    CSU-2172 买一送一

    Description

    ICPCCamp 有 n 个商店,用 1, 2, …, n 编号。对于任意 i > 1,有从商店 (p_i)i 的单向道路。 同时,商店 i 出售类型为 (a_i) 的商品。

    Bobo 从商店 1 出发前往商店 i。他要在两个不同的商店购买商品(包括商店 1 和 i)。设他先购买的商品类型是 x,后购买的商品类型是 y,他用 (f_i) 表示不同的有序对 ⟨x, y⟩ 的数量。 求出 (f_2, f_3, …, f_n) 的值。

    • 1 ≤ n ≤ (10^5)
    • 1 ≤ (p_i) < i
    • 1 ≤ (a_i) ≤ n
    • n 的总和不超过 5 × (10^5).

    Input

    输入文件包含多组数据,请处理到文件结束。

    每组数据的第一行包含 1 个整数 n.

    第二行包含 (n − 1) 个整数 (p_2, p_3, …, p_n).

    第三行包含 n 个整数 (a_1, a_2, …, a_n).

    Output

    对于每组数据输出 (n − 1) 个整数表示 (f_2, f_3 … f_n).

    Sample Input

    3
    1 2
    1 2 3
    3
    1 1
    1 2 3
    4
    1 2 3
    1 3 2 3
    

    Sample Output

    1
    3
    1
    1
    1
    3
    5
    

    Hint

    对于第三个样例,当 i = 4 时,可能的有序对 ⟨x, y⟩ 有 ⟨1, 2⟩,⟨1, 3⟩,⟨2, 3⟩,⟨3, 2⟩,⟨3, 3⟩ 共 5 种。所以 (f_4 = 5).


    题解

    这个题是一道搜索题,一个点的有序对数目等于它上一个点的有序对数目+到目前为止出现过的商品总数-这个点上一次出现时的有序对数目(避免重复计算),我们用一个pre数组记录一下上一个该商品出现时的商品数目,用一个vis数组记录一下一个商品是否出现过,回溯一下就可以AC了

    #include<bits/stdc++.h>
    #define maxn 100050
    using namespace std;
    vector<int> G[maxn];
    int a[maxn];
    long long f[maxn];
    int vis[maxn];
    long long pre[maxn];
    void dfs(int u, int fa, int cnt) {
    	for (int i = 0; i < G[u].size(); i++) {
    		int v = G[u][i];
    		if (!vis[a[u]]) cnt++;
    		vis[a[u]]++;
    		f[v] = f[u] + cnt - pre[a[v]];
    		int tmp = pre[a[v]];
    		pre[a[v]] = cnt;
    		dfs(v, u, cnt);
    		vis[a[u]]--;
    		if (vis[a[u]] == 0) cnt--;
    		pre[a[v]] = tmp;
    	}
    }
    int main() {
    	int n;
    	while (scanf("%d", &n) != EOF) {
    		memset(f, 0, sizeof(f));
    		memset(vis, 0, sizeof(vis));
    		for (int i = 0; i <= n; i++) {
    			G[i].clear();
    		}
    		for (int i = 2; i <= n; i++) {
    			int x;
    			scanf("%d", &x);
    			G[x].push_back(i);
    		}
    		for (int i = 1; i <= n; i++) {
    			scanf("%d", &a[i]);
    		}
    		if (n == 1) continue;
    		dfs(1, 0, 0);
    		for (int i = 2; i <= n; i++) {
    			printf("%lld
    ", f[i]);
    		}
    	}
    	return 0;
    }
    /**********************************************************************
    	Problem: 2172
    	User: Artoriax
    	Language: C++
    	Result: AC
    	Time:576 ms
    	Memory:17568 kb
    **********************************************************************/
    
    
  • 相关阅读:
    leetcode 279. Perfect Squares
    leetcode 546. Remove Boxes
    leetcode 312. Burst Balloons
    leetcode 160. Intersection of Two Linked Lists
    leetcode 55. Jump Game
    剑指offer 滑动窗口的最大值
    剑指offer 剪绳子
    剑指offer 字符流中第一个不重复的字符
    leetcode 673. Number of Longest Increasing Subsequence
    leetcode 75. Sort Colors (荷兰三色旗问题)
  • 原文地址:https://www.cnblogs.com/artoriax/p/10351632.html
Copyright © 2011-2022 走看看