#include using namespace std; #define ALL(x) x.begin(),x.end() #define rep(i,n) for(int i=0;i<(n);i++) #define debug(v) cout<<#v<<":";for(auto x:v){cout<bool chmax(T &a,const T &b){if(abool chmin(T &a,const T &b){if(b ostream &operator<<(ostream &os,const pair&p){ os< ostream &operator<<(ostream &os,const vector&v){ for(int i=0;i<(int)v.size();i++) os< struct rerooting{ using F=function;//集合,頂点番号 using M=function; int V; vector> G; vector> dp; vector ans; // dp_v = g(merge(f(dp_c1,c1),...,f(dp_ck,ck)),v) F f,g; // TxN->T M merge;// TxT->T,子を集約する関数,モノイド T gen; //gen: mergeの元 rerooting(int V,F f,M merge,T gen,F g=[](T a,int b){return a;}) :V(V),f(f),merge(merge),gen(gen),g(g),G(V),dp(V),ans(V,gen){} //bidirectional void add_edge(int a,int b){ G[a].push_back(b); G[b].push_back(a); } T dfs1(int pre,int now){ T ret=gen; for(int i=0;i lsum(G[now].size()+1),rsum(G[now].size()+1);//親も混ぜて累積 lsum[0]=gen;rsum[G[now].size()]=gen; for(int i=0;i0;i--) rsum[i-1]=merge(rsum[i],f(dp[now][i-1],G[now][i-1])); for(int i=0;i; signed main(){ int n;cin>>n; string s;cin>>s; auto f=[&](T t,int idx){return t;}; auto merge=[&](T a,T b){return T(get<0>(a)+get<0>(b),get<1>(a)+get<1>(b),0);}; auto g=[&](T a,int idx){ auto [w,ww,cww]=a; if(s[idx]=='c') return T(w,ww,ww); else return T(w+1,ww+w,cww); }; rerooting R(n,f,merge,T(0,0,0),g); rep(i,n-1){ int u,v;cin>>u>>v;u--,v--; R.add_edge(u,v); } R.build(); ll ans=0; rep(i,n)if(s[i]=='c')ans+=get<2>(R.ans[i]); cout<