Set F[I][J] is the number of the connected block of J points in the diagram I, and can be maintained by heuristic merging in $o (Dn\log N) $ in the time of adding edges.
For each point, set h[i] is the hash value of f[j][i], if the two points hash value is equal, they are connected in the D-map.
#include <cstdio>typedef unsigned long long ll;const int d=200,n=5002,m=262143;int d,n,m,i,j,x,y,z,ans;int F[D][N ],s[d][n],g[d][n],v[d*n*2],nxt[d*n*2],ed;ll pow[d],h[n];struct e{ll v;int w,nxt;} E[n];int g[m+1],res[n],cur;inline void Read (int&a) {char c;while (!) ( ((C=getchar ()) >= ' 0 ') && (c<= ' 9 ')); a=c-' 0 '; while (((C=getchar ()) >= ' 0 ') && (c<= ' 9 ')) (a*= Ten) +=c-' 0 ';} inline void Add (int z,int x,int y) {v[++ed]=y;nxt[ed]=g[z][x];g[z][x]=ed;} inline void ins (ll v) {int u=v&m,i=g[u]; for (; i;i=e[i].nxt) if (e[i].v==v) {Ans+=e[i].w*2+1;e[i].w++;return;} Ans++,e[i=res[cur--]].v=v,e[i].w=1,e[i].nxt=g[u],g[u]=i;} inline void del (ll v) {int u=v&m,i=g[u],j=i; if (e[i].v==v) {ans-=e[i].w*2-1; if (! ( --E[I].W)) g[u]=e[res[++cur]=i].nxt; Return } for (I=E[I].NXT;I;J=I,I=E[I].NXT) if (e[i].v==v) {ans-=e[i].w*2-1; if (! ( --E[I].W)) e[j].nxt=e[res[++cur]=i].nxt; Return }}void dfs (int z,int x,int y,int t) {del (h[x]); H[X]-=POW[Z]*F[Z][X]; f[z][x]=t; INS (H[x]+=POW[Z]*T); for (int i=g[z][x];i;i=nxt[i]) if (v[i]!=y) DFS (z,v[i],x,t);} inline void merge (int z,int x,int y) {if (f[z][x]==f[z][y]) return; if (S[z][f[z][x]]>s[z][f[z][y]]) {int t=x;x=y;y=t;} S[Z][F[Z][Y]]+=S[Z][F[Z][X]]; Add (Z,x,y), add (z,y,x); DFS (Z,x,y,f[z][y]);} int main () {read (d), read (n), read (m); for (pow[0]=i=1;i<d;i++) pow[i]=pow[i-1]*10007; for (i=1;i<=n;i++) res[++cur]=i; For (I=1;i<=n;ins (h[i++))) for (j=0;j<d;j++) f[j][i]=i,s[j][i]=1,h[i]+=pow[j]*i; while (m--) read (x), read (y), read (z), merge (--z,x,y), printf ("%d\n", ans); return 0;}
BZOJ4298: [Ontak2015]bajtocja