#pragma once
structRangeUnionFind{vector<int>data,left,right;RangeUnionFind(intN):data(N,-1){left.resize(N);right.resize(N);iota(begin(left),end(left),0);iota(begin(right),end(right),1);}intfind(intk){returndata[k]<0?k:data[k]=find(data[k]);}intunite(intx,inty){if((x=find(x))==(y=find(y)))returnfalse;if(data[x]>data[y])swap(x,y);data[x]+=data[y];data[y]=x;left[x]=min(left[x],left[y]);right[x]=max(right[x],right[y]);returntrue;}// unite [l, r)voidrange_unite(intl,intr){if((l=max(l,0))>=(r=min(r,(int)data.size())))return;intm;while((m=right[find(l)])<r){assert(left[find(m)]==m);unite(l,m);}}intsize(intk){return-data[find(k)];}intsame(intx,inty){returnfind(x)==find(y);}};
#line 2 "data-structure/range-union-find.hpp"
structRangeUnionFind{vector<int>data,left,right;RangeUnionFind(intN):data(N,-1){left.resize(N);right.resize(N);iota(begin(left),end(left),0);iota(begin(right),end(right),1);}intfind(intk){returndata[k]<0?k:data[k]=find(data[k]);}intunite(intx,inty){if((x=find(x))==(y=find(y)))returnfalse;if(data[x]>data[y])swap(x,y);data[x]+=data[y];data[y]=x;left[x]=min(left[x],left[y]);right[x]=max(right[x],right[y]);returntrue;}// unite [l, r)voidrange_unite(intl,intr){if((l=max(l,0))>=(r=min(r,(int)data.size())))return;intm;while((m=right[find(l)])<r){assert(left[find(m)]==m);unite(l,m);}}intsize(intk){return-data[find(k)];}intsame(intx,inty){returnfind(x)==find(y);}};