#pragma once
// ある連結成分の各頂点に加算出来るtemplate<typenameAbelGroup>classApplyUnionFind{usingT=typenameAbelGroup::value_type;size_tn,num;std::vector<size_t>sz,parent;std::vector<T>value;public:ApplyUnionFind()=default;ApplyUnionFind(size_tn):n(n),num(n),sz(n,1),parent(n),value(n,AbelGroup::unit()){std::iota(parent.begin(),parent.end(),0);}ApplyUnionFind(conststd::vector<T>&v):n(v.size()),num(n),sz(n,1),parent(n),value(v){std::iota(parent.begin(),parent.end(),0);}size_tleader(intx){assert(0<=xandx<n);if(parent[x]==x)returnx;if(parent[parent[x]]==parent[x])returnparent[x];std::stack<size_t>sta;while(parent[x]!=x){sta.push(x);x=parent[x];}Tsum=AbelGroup::unit();while(sta.size()){size_tv=sta.top();sta.pop();AbelGroup::Rchop(sum,value[v]);value[v]=sum;parent[v]=x;}returnx;}Tget(intx){if(x==leader(x))returnvalue[x];returnAbelGroup::op(value[x],value[parent[x]]);}// x と連結な頂点全体に *=avoidmultiply(intx,Ta){x=leader(x);AbelGroup::Rchop(value[x],a);}boolsame(intx,inty){assert(0<=xandx<nand0<=yandy<n);returnleader(x)==leader(y);}boolmerge(intx,inty){assert(0<=xandx<nand0<=yandy<n);x=leader(x);y=leader(y);if(x==y)returnfalse;if(sz[x]<sz[y])std::swap(x,y);sz[x]+=sz[y];parent[y]=x;AbelGroup::Rchop(value[y],AbelGroup::inverse(value[x]));num--;returntrue;}intsize(constintx){assert(0<=xandx<n);returnsz[leader(x)];}intcount()const{returnnum;}};
#line 2 "library/datastructure/unionfind/ApplyUnionFind.hpp"
// ある連結成分の各頂点に加算出来るtemplate<typenameAbelGroup>classApplyUnionFind{usingT=typenameAbelGroup::value_type;size_tn,num;std::vector<size_t>sz,parent;std::vector<T>value;public:ApplyUnionFind()=default;ApplyUnionFind(size_tn):n(n),num(n),sz(n,1),parent(n),value(n,AbelGroup::unit()){std::iota(parent.begin(),parent.end(),0);}ApplyUnionFind(conststd::vector<T>&v):n(v.size()),num(n),sz(n,1),parent(n),value(v){std::iota(parent.begin(),parent.end(),0);}size_tleader(intx){assert(0<=xandx<n);if(parent[x]==x)returnx;if(parent[parent[x]]==parent[x])returnparent[x];std::stack<size_t>sta;while(parent[x]!=x){sta.push(x);x=parent[x];}Tsum=AbelGroup::unit();while(sta.size()){size_tv=sta.top();sta.pop();AbelGroup::Rchop(sum,value[v]);value[v]=sum;parent[v]=x;}returnx;}Tget(intx){if(x==leader(x))returnvalue[x];returnAbelGroup::op(value[x],value[parent[x]]);}// x と連結な頂点全体に *=avoidmultiply(intx,Ta){x=leader(x);AbelGroup::Rchop(value[x],a);}boolsame(intx,inty){assert(0<=xandx<nand0<=yandy<n);returnleader(x)==leader(y);}boolmerge(intx,inty){assert(0<=xandx<nand0<=yandy<n);x=leader(x);y=leader(y);if(x==y)returnfalse;if(sz[x]<sz[y])std::swap(x,y);sz[x]+=sz[y];parent[y]=x;AbelGroup::Rchop(value[y],AbelGroup::inverse(value[x]));num--;returntrue;}intsize(constintx){assert(0<=xandx<n);returnsz[leader(x)];}intcount()const{returnnum;}};