zoukankan      html  css  js  c++  java
  • 2019牛客国庆集训派对day3 买一送一

    题目链接:

    题意:有n个点,n-1条单向边,每个点都销售一类商品

    问从点1开始走,买第一样商品类型为x,买第二样商品类型为y,问不同有序对<x,y>的数量

    解法:

    col[i]表示这个点的商品类型

    last[col[i]]表示从1到点i过程中,点i的商品类型上次出现的时候的点的父亲

    vis[col[i]]表示从1到点i过程中,点i的商品类型经过次数

    num[i]表示从1到点i过程中不同商品类型数量和

    每次扫到新的点v时,(u为v的父亲) num[u] - num[last[col[v]]]就是需要更新的对数

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int M = 1e5 + 10;
    const int mod = 1e9 + 7;
    int num[M], vis[M], anss[M], ans, cnt, col[M], head[M], last[M];
    struct node{
        int next, to;
    }edge[M];
    void add_edge(int u, int v) {
        edge[++cnt].next = head[u];
        edge[cnt].to = v;
        head[u] = cnt;
    }
    void dfs(int u, int sum, int ans) {
        for(int i = head[u]; i; i = edge[i].next) {
            int v = edge[i].to;
            int t = 0;
            int lastt = last[col[v]];
            vis[col[v]]++;
            if(vis[col[v]] == 1) num[v] = num[u] + 1;
            else num[v] = num[u];
            t = num[u] - num[last[col[v]]];
            last[col[v]] = u;
            //printf("%d %d %d
    ", v, col[v], last[col[v]]);
            anss[v] = ans + t;
            if(vis[col[v]] == 1) dfs(v, sum + 1, ans + t);
            else dfs(v, sum + 1, ans + t);
            vis[col[v]]--;
            last[col[v]] = lastt;
        }
    }
    int main(){
        int n;
        while(~scanf("%d", &n)){
            cnt = 0;
            memset(head, 0, sizeof(head));
            for(int i = 1; i <= n; i++) num[i] = 0, last[i] = 0, vis[i] = 0, anss[i] = 0;
            for(int i = 2; i <= n; i++) {
                int u;
                scanf("%d", &u);
                add_edge(u, i);
            }
            for(int i = 1; i <= n; i++)
                scanf("%d", &col[i]);
            vis[col[1]]++;
            num[1] = 1;
            dfs(1, 1, 0);
    //        for(int i = 1; i <= n; i++) {
    //            printf("%d ", num[i]);
    //        }
    //        printf("
    ");
            for(int i = 2; i <= n; i++) {
                printf("%d
    ", anss[i]);
            }
        }
        return 0;
    }
    /*
    3
    1 2
    1 2 3
    3
    1 1
    1 2 3
    4
    1 2 3
    1 3 2 3
    7
    1 1 3 2 4 2
    3 3 3 4 5 3 3
    7
    1 1 3 2 4 2
    2 3 3 4 5 3 3
    */
    View Code
  • 相关阅读:
    Android(java)学习笔记68:使用proguard混淆android代码
    SGU 194 Reactor Cooling
    关于流量有上下界的网络流问题的求解
    关于最小割的求解方法
    HDU 5311 Hidden String
    POJ 3548 Restoring the digits
    POJ 2062 HDU 1528 ZOJ 2223 Card Game Cheater
    ZOJ 1967 POJ 2570 Fiber Network
    HDU 1969 Pie
    HDU 1956 POJ 1637 Sightseeing tour
  • 原文地址:https://www.cnblogs.com/linglinga/p/12077145.html
Copyright © 2011-2022 走看看