The 2019 ACM-ICPC Shannxi J. And And And (点分治模板题)

J. And And And

A tree is a connected graph without cycles. You are given a rooted tree with nn nodes, labeled from 1ton1ton. The tree is rooted at node 11. The parent of the ii-th node is faifai​​. The edge weight between the ii-th node and faifai​​ is wiwi​

  • E(u,v)E(u,v) is a set of all the nodes through a path which is from uu to vv, including uu and vv. For example,

E(5,3)={5,2,1,3},E(4,6)={4,3,6},E(2,5)={2,5}E(5,3)={5,2,1,3},E(4,6)={4,3,6},E(2,5)={2,5}

  • X(u,v)X(u,v) represents the XOR of all edge weights on the path from uu to vv

For example, in the case given above,

X(1,5)=1X(1,5)=1 ⁡xorxor 1=01=0,X(4,6)=1X(4,6)=1 ⁡xorxor 3=23=2,X(2,5)=1X(2,5)=1,X(3,5)=2X(3,5)=2 xorxor 11 xorxor 11 =2=2⁡You need to calculate the answer to the following formula:

∑u=1n∑v=1n∑u′∈E(u,v)∑v′∈E(u,v)[u<v][u′<v′][X(u′,v′)=0]u=1∑n​v=1∑n​u′∈E(u,v)∑​v′∈E(u,v)∑​[u<v][u′<v′][X(u′,v′)=0]

The answer modulo 10000000071000000007

  • XOR is equivalent to '^' in c / c++ / java / python. If both bits in the compared position of the bit patterns are 00 or 11, the bit in the resulting bit pattern is 00, otherwise 11.

Input

Each test file contains a single test case. In each test file:

The first line contains one integer n(1≤n≤105)n(1≤n≤105) — the number of nodes in the tree.

Then n−1n−1 lines follow. ii-th line contains two integers fai(1≤fai<i)fai​​(1≤fai​​<i), wi(0≤wi≤1018)wi​(0≤wi​≤1018) —The parent of the ii-th node and the edge weight between the ii-th node and fai(ifai​​(istart from 2)2).

Output

Print a single integer — the answer of this problem, modulo 10000000071000000007.

样例输入1 复制

2 
12

样例输出1 复制

0

样例输入2 复制

5 
1 0 
2 0 
3 0 
4 0

样例输出2 复制

35
//#include<bits/stdc++.h>
#include<unordered_map>
//#include<unordered_set>
#include<iostream>
#include<sstream>
#include<iterator>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<vector>
#include<bitset>
#include<climits>
#include<queue>
#include<iomanip>
#include<cmath>
#include<stack>
#include<map>
#include<ctime>
#include<new>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define MT(a, b) memset(a,b,sizeof(a))
const int INF  =  0x3f3f3f3f;
const int O    =  1e6;
const int mod  =  1000000007;
const int maxn =  4e5 +5;
const double PI  =  acos(-1.0);
const double E   =  2.718281828459;
const double eps = 1e-8;


struct dd { LL to, val, next;
    dd () {}
    dd (LL x, LL y, LL z) : to(x), val(y), next(z) {}
}e[maxn];
LL head[maxn], cnt = 0;
void add(LL u, LL v, LL w) { e[cnt] = dd (v, w, head[u]); head[u] = cnt ++; }

LL n, root, size, max_son[maxn], sum[maxn], vis[maxn], pin[maxn];

void get_root(LL u, LL fa, bool flag) {
    max_son[u] = 0; sum[u] = 1;
    for(LL i=head[u]; i!=-1; i=e[i].next) {
        LL v = e[i].to;
        if(vis[v] || v == fa) continue;
        get_root(v, u, flag);
        sum[u] += sum[v];
        max_son[u] = max(max_son[u], sum[v]);
    }
    if(flag) pin[u] = sum[u];
    max_son[u] = max(max_son[u], size - sum[u]);
    if(max_son[u] <= max_son[root]) root = u;
}

unordered_map<LL, LL> now, rem;

LL ans = 0;

void get_now(LL u, LL fa, LL res) {
    now[res] = (now[res] + (pin[u] > pin[fa] ? n - pin[fa] : pin[u])) % mod;
    for(LL i=head[u]; i!=-1; i=e[i].next) {
        LL v = e[i].to;
        if(v == fa || vis[v]) continue;
        get_now(v, u, res ^ e[i].val);
    }
}

void solve(LL u) {
    for(LL i=head[u]; i!=-1; i=e[i].next) {
        LL v = e[i].to;
        if(vis[v]) continue;
        now.clear(); get_now(v, u, e[i].val);
        LL d = pin[u] > pin[v] ? n - pin[v] : pin[u];
        ans = (ans + d * now[0] % mod) % mod;
        for(auto j=now.begin(); j!=now.end(); j++) {
            LL x = j->first, y = j->second;
            ans = (ans + y * rem[x] % mod ) % mod;
            rem[x] = (rem[x] + y) % mod;
        }
    }
}

void fun(LL u) {
     vis[u] = 1; rem.clear(); solve(u);
    for(LL i=head[root]; i!=-1; i=e[i].next) {
        LL v = e[i].to;
        if( vis[v]) continue;
        size = sum[v];
        max_son[ root = 0] = INF; get_root(v, -1, 0);
        fun(root);
    }

}

int main(){
    MT(head, -1);
    scanf("%lld", &n);
    for(LL i=2; i<=n; i++) {
        LL v, w; scanf("%lld%lld", &v, &w);
        add (i, v, w); add (v, i, w);
    }
    size = n; max_son[root = 0] = INF; get_root(1, -1, 1);
    fun(root);
    printf("%lld\n", ans);
    return 0;
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值