Untitled
small to large with keeping at each node map corresponding to its subtreeunknown
c_cpp
a year ago
3.5 kB
8
Indexable
#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
}
Editor is loading...
Leave a Comment