F - Strange Memory
阿新 • • 發佈:2020-11-12
/* *@author spnooyseed */ #pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline") #pragma GCC optimize(3 , "Ofast" , "inline") #pragma GCC optimize("Ofast") #pragma GCC target("avx,avx2,fma") #pragma GCC optimization("unroll-loops") #include <iostream> #include <cstdio> #include <algorithm> #include <unordered_map> #include <vector> #include <map> #include <list> #include <queue> #include <cstring> #include <cstdlib> #include <ctime> #include <cmath> #include <stack> #include <set> #include <bitset> #include <deque> using namespace std ; #define ios ios::sync_with_stdio(false) , cin.tie(0) #define x first #define y second #define pb push_back #define ls rt << 1 #define rs rt << 1 | 1 typedef long long ll ; const double esp = 1e-6 , pi = acos(-1) ; typedef pair<int , int> PII ; const int N = 2e6 + 10 , INF = 0x3f3f3f3f , mod = 1e9 + 7 , M = 1e5 + 10; int a[M] , n ; vector<int> v[M] ; int sz[M] , son[M] , vis[M] ; ll ans ; ll h[N][22][2] ; void dfs_rt(int u , int f) { sz[u] = 1 ; for(auto x : v[u]) { if(x == f) continue ; dfs_rt(x , u) ; sz[u] += sz[x] ; if(!son[u] || sz[son[u]] < sz[x]) son[u] = x ; } } void add(int u , int keep) { int t = a[u] ; for(int i = 0 ;i < 20 ;i ++ ) h[t][i][u % 2] += keep , u /= 2 ; } void count(int u , int f , int lca) { int t = a[u] ^ a[lca] , m = u ; for(int i = 0 ;i < 20 ;i ++ ) ans += 1ll * h[t][i][1 - m % 2] * (1 << i) , m /= 2 ; for(auto x : v[u]) { if(x == f) continue ; count(x , u , lca) ; } } void dfs1(int u , int f , int keep) { add(u , keep) ; for(auto x : v[u]) { if(x == f) continue ; dfs1(x , u , keep) ; } } void update(int u , int f , int keep) { for(auto x : v[u]) { if(x == f || vis[x]) continue ; if(keep == 1) count(x , u , u) ; dfs1(x , u , keep) ; } add(u , keep) ; } void solve(int u , int f , int keep) { for(auto x : v[u]) { if(x == f || x == son[u]) continue ; solve(x , u , 0) ; } if(son[u]) solve(son[u] , u , 1) , vis[son[u]] = 1 ; // cout << u << " " << f << " " << keep << endl ; // puts("before") ; // for(int i = 1; i <= 6 ;i ++ ) { // for(int j = 0 ;j < 4 ;j ++ ) // cout << "value = "<< i << " idx = " << j << " idx0 = " << h[i][j][0] << " idx1 = " << h[i][j][1] << endl ; // } update(u , f , 1) ; // cout << u << " " << f << " " << keep << endl ; // puts("after") ; // for(int i = 1; i <= 6 ;i ++ ) { // for(int j = 0 ;j < 4 ;j ++ ) // cout << "value = "<< i << " idx = " << j << " idx0 = " << h[i][j][0] << " idx1 = " << h[i][j][1] << endl ; // } if(vis[son[u]]) vis[son[u]] = 0 ; if(!keep) update(u , f , -1) ; // cout << u << " " << f << " " << keep << endl ; // puts("last") ; // for(int i = 1; i <= 6 ;i ++ ) { // for(int j = 0 ;j < 4 ;j ++ ) // cout << "value = "<< i << " idx = " << j << " idx0 = " << h[i][j][0] << " idx1 = " << h[i][j][1] << endl ; // } } int work() { scanf("%d" , &n) ; for(int i = 1; i <= n ;i ++ ) scanf("%d" , &a[i]) ; for(int i = 1; i < n ;i ++ ) { int a , b ; scanf("%d%d" , &a , &b) ; v[a].push_back(b) , v[b].push_back(a) ; } dfs_rt(1 , 0) ; // for(int i = 1; i <= n ;i ++ ) // cout << son[i] << " " ; // puts("") ; solve(1 , 1 , 0) ; cout << ans << endl ; return 0 ; } int main() { // freopen("C://Users//spnooyseed//Desktop//in.txt" , "r" , stdin) ; // freopen("C://Users//spnooyseed//Desktop//out.txt" , "w" , stdout) ; work() ; return 0 ; } /* */