BZOJ 4530: [Bjoi2014]大融合
首先把原树建出来,然后线段树合并,dfs序,查询子树大小
线段树合并真是一个神奇的东西
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | #include<cstdio> #include<algorithm> using namespace std; int ti,cnt,dfn[100005],Fa[100005],Dep[100005],root[100005],ls[2000005],rs[2000005],tree[2000005],F[100005],sz[100005],cas[100005],x[100005],y[100005],last[100005],ed[100005]; char s[5]; struct node{ int to,next; }e[200005]; void add( int a, int b){ e[++cnt].to=b; e[cnt].next=last[a]; last[a]=cnt; } void dfs( int x, int fa){ dfn[x]=++ti; Fa[x]=fa; for ( int i=last[x]; i; i=e[i].next){ int V=e[i].to; if (V==fa) continue ; Dep[V]=Dep[x]+1; dfs(V,x); } ed[x]=ti; } int query( int t, int l, int r, int x, int y){ if (!t) return 0; if (r<x || l>y) return 0; if (l>=x && r<=y) return tree[t]; int mid=(l+r)>>1; return query(ls[t],l,mid,x,y)+query(rs[t],mid+1,r,x,y); } void insert( int &t, int l, int r, int x){ if (!t) t=++cnt; tree[t]++; if (l==r) return ; int mid=(l+r)>>1; if (x<=mid) insert(ls[t],l,mid,x); else insert(rs[t],mid+1,r,x); } int merge( int x, int y){ if (!x || !y) return x^y; tree[x]+=tree[y]; ls[x]=merge(ls[x],ls[y]); rs[x]=merge(rs[x],rs[y]); return x; } int find( int x){ if (F[x]!=x) F[x]=find(F[x]); return F[x]; } int main(){ int n,m; scanf ( "%d%d" ,&n,&m); for ( int i=1; i<=m; i++){ scanf ( "%s%d%d" ,s,&x[i],&y[i]); if (s[0]== 'A' ) cas[i]=0; else cas[i]=1; } for ( int i=1; i<=m; i++) if (!cas[i]){ add(x[i],y[i]); add(y[i],x[i]); } for ( int i=1; i<=n; i++) F[i]=i,sz[i]=1; for ( int i=1; i<=n; i++) if (!dfn[i]) dfs(i,0); for ( int i=1; i<=n; i++) insert(root[i],1,n,dfn[i]); for ( int i=1; i<=m; i++) if (cas[i]==0){ int fx=find(x[i]),fy=find(y[i]); F[fy]=fx; sz[fx]+=sz[fy]; root[fx]=merge(root[fx],root[fy]); } else if (cas[i]==1){ int X=x[i],Y=y[i]; if (Dep[X]>Dep[Y]) swap(X,Y); int ans=sz[find(X)]; int ANS=query(root[find(X)],1,n,dfn[Y],ed[Y]); printf ( "%lld\n" ,1ll*ANS*(ans-ANS)); } return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步