Codeforces Bubble Cup 8 - Finals [Online Mirror] B. Bribes lca

题目链接:

http://codeforces.com/contest/575/problem/B

题解:

 把链u,v拆成u,lca(u,v)和v,lca(u,v)(v,lca(u,v)是倒过来的)。这样就只要考虑自下而上的线性结构了,可以用前缀和的思想来做成段更新。

代码:

#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int maxn = 1e5 + 10;
const int DEG = 22;
const int mod = 1e9 + 7;
typedef __int64 LL;

struct Edge {
    int v, type;
    Edge() {}
    Edge(int v, int type) :v(v), type(type) {}
};

int n,q;
vector<Edge> egs;
vector<int> G[maxn];

int dep[maxn], anc[maxn][DEG],up[maxn];
void dfs(int u,int fa) {
    dep[u] = dep[fa] + 1;
    anc[u][0] = fa;
    for (int i = 1; i < DEG; i++) {
        int f = anc[u][i - 1];
        anc[u][i] = anc[f][i - 1];
    }
    for (int i = 0; i < G[u].size(); i++) {
        Edge& e = egs[G[u][i]];
        if (e.v == fa) continue;
        up[e.v] = -e.type;
        dfs(e.v, u);
    }
}

int cnt[2][maxn];
int Lca(int u, int v) {
    if (dep[u] < dep[v]) swap(u, v);
    for (int i = DEG - 1; i >= 0; i--) {
        if (dep[anc[u][i]]>=dep[v]) {
            u = anc[u][i];
        }
    }
    if (u == v) return u;
    for (int i = DEG - 1; i >= 0; i--) {
        if (anc[u][i] != anc[v][i]) {
            u = anc[u][i];
            v = anc[v][i];
        }
    }
    //printf("u:%d,v:%d\n", u, v);
    return anc[u][0];
}

void dfs2(int u, int fa) {
    for (int i = 0; i < G[u].size(); i++) {
        Edge& e = egs[G[u][i]];
        if (e.v == fa) continue;
        dfs2(e.v, u);
        cnt[0][u] += cnt[0][e.v];
        cnt[1][u] += cnt[1][e.v];
    }
}

void addEdge(int u, int v, int type) {
    egs.push_back(Edge(v, type));
    G[u].push_back(egs.size() - 1);
}

LL fast_pow(int n) {
    LL ret = 1,x=2;
    while (n) {
        if (n & 1) ret *= x, ret %= mod;
        x *= x, x %= mod;
        n /= 2;
    }
    return ret;
}

void init() {
    for (int i = 0; i < maxn; i++) G[i].clear();
    egs.clear();
    memset(anc, 0, sizeof(anc));
    memset(dep, 0, sizeof(dep));
    memset(up, 0, sizeof(up));
    memset(cnt, 0, sizeof(cnt));
}

int main() {
    scanf("%d", &n);
    init();
    for (int i = 0; i < n - 1; i++) {
        int u, v, type;
        scanf("%d%d%d", &u, &v, &type);
        if (type == 0) {
            addEdge(u, v, 0);
            addEdge(v, u, 0);
        }
        else {
            addEdge(u, v, 1);
            addEdge(v, u, -1);
        }
    }
    dfs(1, 0);
    //for (int i = 1; i <= n; i++) {
    //    printf("%d:(%d)",i,dep[i]);
    //    for (int j = 0; j < 20; j++) {
    //        printf("%d ", anc[i][j]);
    //    }
    //    printf("\n");
    //}
    scanf("%d", &q);
    int s = 1, t;
    while (q--) {
        //scanf("%d%d", &s, &t);
        //printf("(%d,%d):%d\n", s, t, Lca(s, t));
        scanf("%d", &t);
        int lca = Lca(s, t);
        //printf("(%d,%d):%d\n", s, t, lca);
        cnt[0][s]++;
        cnt[0][lca]--;
        cnt[1][t]++;
        cnt[1][lca]--;
        s = t;
    }
    dfs2(1, 0);
    LL ans = 0;
    for (int i = 1; i <= n; i++) {
        if (up[i] == -1) {
            ans += fast_pow(cnt[0][i]) - 1;
            ans = (ans + mod) % mod;
        }
        else if (up[i] == 1) {
            ans += fast_pow(cnt[1][i]) - 1;
            ans = (ans + mod) % mod;
        }
    }
    printf("%I64d\n", ans);
    return 0;
}
/*
7
1 2 0
1 3 0
2 4 0
2 5 0
3 6 0
3 7 0

*/

 

posted @ 2016-06-24 00:30  fenicnn  阅读(240)  评论(0编辑  收藏  举报