打完欧拉序列转rmq发现超了空间。。再打离线发现不能处理距离。。最后改了改欧拉序列rmq不MLE了。。结果发现跑的还没有倍增快。。。/(ㄒoㄒ)/~~以后一定用倍增了。
对于x,y,z,可以发现他们的lca只有两个,即有一个lca与其他两个不同(三个都相同除外),那么这个lca就是集合点。。没了。抑或一下可能会方便一点。
AC代码如下:
#include<iostream> #include<cstdio> #include<cstring> #define N 1000005 using namespace std; int n,m,cnt,tot,fst[N],pnt[N],nxt[N],d[N],f[N][21],mi2[21],lg2[N],pos[N]; int read(){ int x=0; char ch=getchar(); while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x; } void add(int aa,int bb){ pnt[++tot]=bb; nxt[tot]=fst[aa]; fst[aa]=tot; } void dfs(int x,int last){ f[pos[x]=++cnt][0]=x; d[x]=d[last]+1; int p; for (p=fst[x]; p; p=nxt[p]) if (pnt[p]!=last){ dfs(pnt[p],x); f[++cnt][0]=x; } } int lca(int x,int y){ x=pos[x]; y=pos[y]; if (x>y) swap(x,y); int k=lg2[y-x+1]; x=f[x][k]; y=f[y-mi2[k]+1][k]; return (d[x]<d[y])?x:y; } int dist(int x,int y){ return d[x]+d[y]-(d[lca(x,y)]<<1); } int main(){ n=read(); m=read(); int i,j; for (i=1; i<n; i++){ int x=read(),y=read(); add(x,y); add(y,x); } dfs(1,0); for (i=2; i<=cnt; i++) lg2[i]=lg2[i>>1]+1; mi2[0]=1; for (i=1; i<=lg2[cnt]; i++) mi2[i]=mi2[i-1]<<1; for (i=1; i<=lg2[cnt]; i++) for (j=1; j<=cnt; j++){ f[j][i]=f[j][i-1]; int k=j+mi2[i-1]; if (k>cnt) continue; if (d[f[k][i-1]]<d[f[j][i]]) f[j][i]=f[k][i-1]; } while (m--){ int x=read(),y=read(),z=read(),tmp=lca(x,y)^lca(x,z)^lca(y,z); printf("%d %d\n",tmp,dist(x,tmp)+dist(y,tmp)+dist(z,tmp)); } return 0; }
by lych
2016.2.10