给定一棵树,10^6个点,有10^6次询问,每次询问给出两个点,问不在这两个点之间的路上的最小的点的编号..
强制在线计算。不可以离线。
乱搞...不过比较复杂...
首先把1号点提成根,然后记录每个点属于1号点的哪个孩子。这样我们就可以判断一条路过不过根节点(即1号节点)。
若不过根节点,则答案显然为1。
若过根节点,则答案为不再这两个到根的链上的最小值,分为3部分,第一个节点所属的根节点的孩子的那个子树,第二个节点所属的根节点的孩子的那个子树,其他子树。
提前预处理出每颗子树的最小值,每颗子树上除去某条链后的最小值,所有子树中的最小次小再次小值,即可做到O(1)的回答。
因为点太多了..所以本机跑都爆栈...应该写非递归的...不过杭电有扩栈的那句话,于是愉快的水过了~
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <algorithm>
using namespace std;
inline int in() {
char c=getchar();
while (c<'0'||c>'9') c=getchar();
int ans=0;
while (c>='0'&&c<='9') {
ans=ans*10+c-'0';
c=getchar();
}
return ans;
}
struct Node {
int f,fe,belong,min1,min2,ans,otm;
bool visited;
};
struct Edge {
int t,ne;
};
Node a[1000001];
Edge b[2000000];
int n,q,bp,min1,min2,min3,x,y;
void print() {
printf("%d %d %d\n",min1,min2,min3);
for (int i=1;i<=n;i++) {
printf("Node:%d belong:%d min1:%d min2:%d ans:%d otm:%d\n",i,a[i].belong,a[i].min1,a[i].min2,a[i].ans,a[i].otm);
}
}
void putedge(int x,int y) {
b[bp].t=y;
b[bp].ne=a[x].fe;
a[x].fe=bp++;
}
void update(int &min1,int &min2,int &min3,int x) {
if (x<=min1) {
min3=min2;
min2=min1;
min1=x;
} else if (x<=min2) {
min3=min2;
min2=x;
} else if (x<=min3) {
min3=x;
}
}
void dfs1(int i) {
a[i].visited=true;
a[i].belong=x;
int min1=n+1,min2=n+1,min3=n+1;
for (int j=a[i].fe;j!=-1;j=b[j].ne) {
if (!a[b[j].t].visited) {
a[b[j].t].f=i;
dfs1(b[j].t);
update(min1,min2,min3,min(b[j].t,a[b[j].t].min1));
}
}
a[i].min1=min1;
a[i].min2=min2;
a[i].visited=false;
}
void dfs2(int i) {
a[i].visited=true;
for (int j=a[i].fe;j!=-1;j=b[j].ne) {
if (!a[b[j].t].visited) {
dfs2(b[j].t);
if (min(b[j].t,a[b[j].t].min1)!=a[i].min1) a[b[j].t].otm=a[i].min1;
else a[b[j].t].otm=a[i].min2;
}
}
a[i].visited=false;
}
void dfs3(int i,int min1) {
a[i].visited=true;
a[i].ans=min(min1,a[i].min1);
for (int j=a[i].fe;j!=-1;j=b[j].ne) {
if (!a[b[j].t].visited) {
dfs3(b[j].t,min(min1,a[b[j].t].otm));
}
}
a[i].visited=false;
}
int getAns(int x,int y) {
if (x==1||y==1) {
x*=y;
if (min1==min(a[x].belong,a[a[x].belong].min1)) return min(a[x].ans,min2);
else return min1;
} else if (a[x].belong!=a[y].belong) {
int tmp1=min(a[x].belong,a[a[x].belong].min1);
int tmp2=min(a[y].belong,a[a[y].belong].min1);
int ans;
if (min1!=tmp1&&min1!=tmp2) ans=min1;
else if (min2!=tmp1&&min2!=tmp2) ans=min2;
else ans=min3;
ans=min(ans,a[x].ans);
ans=min(ans,a[y].ans);
return ans;
} else return 1;
}
int main() {
int i,ans,j;
while (scanf("%d%d",&n,&q)!=EOF) {
for (i=1;i<=n;i++) {
a[i].fe=-1;
a[i].visited=false;
}
bp=0;
for (i=1;i<n;i++) {
x=in();y=in();
putedge(x,y);
putedge(y,x);
}
min1=min2=min3=n+1;
a[1].visited=true;
for (j=a[1].fe;j!=-1;j=b[j].ne) {
x=b[j].t;
dfs1(b[j].t);
dfs2(b[j].t);
dfs3(b[j].t,n+1);
//printf("update %d %d %d %d\n",min1,min2,min3,min(x,a[x].min1));
update(min1,min2,min3,min(x,a[x].min1));
}
//print();
ans=0;
for (i=0;i<q;i++) {
x=in();y=in();
x^=ans;y^=ans;
ans=getAns(x,y);
printf("%d\n",ans);
}
}
return 0;
}