Untitled
small to large with keeping at each node map corresponding to its subtree#include <bits/stdc++.h> using namespace std ; #ifndef ONLINE_JUDGE #include "debugger.cpp" #else #define debug(...) #define debugArr(...) #define show(...) #endif template<typename... T>void read(T&... args) {((cin >> args), ...);} template<typename... T>void print(T&&... args) {((cout << args ), ...);} template <class T> using V = vector<T>; #define pb push_back #define int long long typedef long long ll ; typedef array<int, 2> pi ; typedef vector<int> vi ; #define len(v) (int)v.size() #define FOR( i , debut, fin) for( ll i = debut ; i<fin ; i++ ) #define all(x) x.begin(), x.end() #define getunique(vt) vt.erase(unique(all(vt)), vt.end()) void YES(bool x) { if (x) cout << ("Yes\n"); else cout << ("No\n"); } void input_output(); const int N = 4e5; int n ; vector<pi>adj[N]; int depth[N] , parent[N] , pfxor[N]; map<int,int>mp[N] ; void calsz ( int nd , int pr , int xpf ){ depth[nd] = 1 ; pfxor[nd] = xpf ; for ( auto &[ch,_]: adj[nd]){ if ( ch == pr ) continue; calsz(ch , nd , xpf ^ _ ); parent[ch] = nd ; depth[nd] += depth[ch]; } } int ans = 0 ; void addto( int nd , int pr , int where) { for ( int bt = 0 ; bt < 28 ; bt++ ){ int x = 1LL << bt ; int need2 = pfxor[nd]^ x ; if ( !mp[where].count(need2)) continue; ans += mp[where][need2] ; } ans += mp[where][pfxor[nd]]; for ( auto &[ch, _ ]: adj[nd]){ if ( ch == pr )continue; addto(ch,nd,where); } } void addtomap ( int nd , int pr , int where) { mp[where][pfxor[nd]]++ ; for ( auto &[ch, _ ]: adj[nd]){ if ( ch == pr )continue; addtomap(ch,nd,where); } } void dfs ( int nd , int pr ){ int MX = -1 , BIG = -1 ; for ( auto &[ch,w]: adj[nd]){ if ( ch == pr ) continue; if( MX < depth[ch]) BIG = ch , MX = depth[ch]; } for ( auto &[ch,w]:adj[nd]){ if ( ch == pr or ch == BIG )continue; dfs(ch,nd); } if( BIG != -1) dfs(BIG,nd); int prfparent =pfxor[nd] ; int needed1 = prfparent ; if ( BIG != -1 ){ swap(mp[nd], mp[BIG]); } ans += mp[nd][needed1] ; for ( int bt = 0 ; bt < 28 ; bt++ ){ int x = 1LL << bt ; int need2 = prfparent ^ x ; if ( !mp[nd].count(need2)) continue; ans += mp[nd][need2] ; } mp[nd][needed1]++ ; for ( auto &[ch,_] :adj[nd]){ if ( ch == pr or ch == BIG ) continue; addto(ch,nd , nd ); addtomap(ch,nd,nd) ; } } void solve(){ read (n); ans = 0 ; FOR (i , 0 , n-1 ){ int u , v ; char a ; read ( u , v , a ); int msk = 1LL << (a- 'a') ; adj[u].push_back({v,msk}); adj[v].push_back({u,msk}); } pfxor[0] = 0 ; calsz(1 , 0 , 0 ); dfs(1,0); print(ans); } int32_t main() { input_output(); int t = 1; for ( int i = 1 ; i <= t ; i++ ){ show("------- Case " , i, "------- : " ); solve(); show("---------------------- .\n \n "); } double Time_elapsed= 1.0 * clock() / CLOCKS_PER_SEC ; debug(Time_elapsed); } void input_output() { cout.tie(0), cin.tie(0), ios_base::sync_with_stdio(0) ; cout << fixed << setprecision(14) ; cerr << fixed << setprecision(14) ; #ifndef ONLINE_JUDGE freopen("inp.txt", "r", stdin); freopen("out.txt", "w", stdout); freopen("err.txt", "w", stderr); #endif }
Leave a Comment