FZSZ Online Judge #815. LCA
题目描述
给定一个 n 个点的有根树,q 次询问 (x,y) 的最近公共祖先
输入格式
一行输入一个正整数 n
以下 n−1 行, 每行输入两个正整数 (x,y), 表示 x→y有一条边
一行输入一个正整数 q
以下 q 行, 每行输入两个正整数 (x,y), 表示询问 lca(x,y)
输出格式
设第 i 次询问的答案为 xixi, 输出 ∑qi=1nq-ixi(mod264)
//不知道有没搞错反正是 ans = ans * n + Lca(x, y);
样例输入
3
1 2
1 3
3
1 2
1 3
2 3
样例输出
13
数据范围
n,q≤106,x,y≤n,
倍增算法(在线处理)
#include<cstdio>
#include<iostream>
#include<cmath>
#define ull unsigned long long
#define BIG 2333333
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
using namespace std;
ull mod;
inline int read(){
char c;
while(c=getchar(),c>'9'||c<'0');
int data=c-48;
while(c=getchar(),c>='0'&&c<='9')
data=(data<<1)+(data<<3)+c-48;
return data;
}
int nxt[BIG],las[BIG],to[BIG],rd[BIG],dep[BIG],fa[BIG][24];
int n,q,tot,x,y;
ull ans;
inline void add(int x,int y){
nxt[++tot]=las[x];
las[x]=tot;
to[tot]=y;
++rd[y];
}
inline void dfs(int now){
for(register int e=las[now];e;e=nxt[e]){
dep[to[e]]=dep[now]+1;
fa[to[e]][0]=now;
dfs(to[e]);
}
}
inline void ST(){
FOR(i,1,20)
FOR(j,1,n)
fa[j][i]=fa[fa[j][i-1]][i-1];
}
inline void swap(int &x,int &y){
int t=x;
x=y;
y=t;
}
inline int LCA(int x,int y){
if(dep[x]<dep[y])
swap(x,y);
for(register int i=20;i>=0;--i)
if(dep[fa[x][i]]>=dep[y])
x=fa[x][i];
if(x==y)
return x;
for(register int i=20;i>=0;--i)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int wr[101];
inline void write(unsigned long long a){
if(!a){
putchar(48);
return;
}
while(a)
wr[++wr[0]]=a%10,a/=10;
while(wr[0])
putchar(48+wr[wr[0]--]);
return;
}
int main(){
n=read();
FOR(i,1,n-1){
x=read();
y=read();
add(x,y);
}
FOR(i,1,n)
if(!rd[i]){
dep[i]=1;
dfs(i);
break;
}
q=read();
ST();
mod=1;
FOR(i,1,63)
mod=(ull)(mod<<1);
while(q--){
x=read();
y=read();
ans=ans*n+LCA(x,y);
if(ans<0){
ans+=mod;
ans+=mod;
}
}
write(ans);
return 0;
}
树链剖分(在线处理)
#include<cstdio>
#include<iostream>
#define BIG 2333333
#define ll unsigned long long
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
using namespace std;
namespace TCP{
int nxt[BIG],las[BIG],to[BIG],deg[BIG];
int dep[BIG],sz[BIG],top[BIG],f[BIG];
int n,m,x,y,tot;
inline void add(int x,int y){
nxt[++tot]=las[x];
las[x]=tot;
to[tot]=y;
++deg[y];
return;
}
inline void dfs1(int now){
sz[now]=1;
for(register int e=las[now];e;e=nxt[e]){
dep[to[e]]=dep[f[to[e]]=now]+1;
dfs1(to[e]);
sz[now]+=sz[to[e]];
}
return;
}
inline void dfs2(int now,int chain){
top[now]=chain;
register int i=0;
for(register int e=las[now];e;e=nxt[e])
if(sz[i]<sz[to[e]])
i=to[e];
if(!i)
return;
dfs2(i,chain);
for(register int e=las[now];e;e=nxt[e])
if(to[e]!=i)
dfs2(to[e],to[e]);
return;
}
inline ll lca(int u,int v){
for(;top[u]!=top[v];dep[top[u]]>dep[top[v]]?u=f[top[u]]:v=f[top[v]]);
return (ll)(dep[u]<dep[v]?u:v);
}
};
using namespace TCP;
namespace DATA{
inline void read(int &x){
char c;
while(c=getchar(),c>'9'||c<'0');
x=c-48;
while(c=getchar(),c>='0'&&c<='9')
x=(x<<1)+(x<<3)+c-48;
return;
}
int wr[51];
inline void write(ll x){
while(x)
wr[++wr[0]]=x%10,x/=10;
while(wr[0])
putchar(48+wr[wr[0]--]);
putchar('\n');
return;
}
};
using namespace DATA;
namespace WORK{
ll ans,mod=1ll;
inline void work(){
read(n);
FOR(i,1,n-1){
read(x);
read(y);
add(x,y);
}
FOR(i,1,n)
if(!deg[i]){
dfs1(i);
dfs2(i,i);
break;
}
FOR(i,1,63)
mod<<=1;
read(m);
while(m--){
read(x);
read(y);
ans=ans*n+lca(x,y);
if(ans<0){
ans+=mod;
ans+=mod;
}
}
write(ans);
}
};
using namespace WORK;
int main(){
work();
return 0;
}
Tarjan(离线处理)
#include<cstdio>
#include<iostream>
#include<vector>
#define BIG 2333333
#define ll unsigned long long
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
using namespace std;
namespace TARJAN{
int n,m,tot;
int x,y,z;
int las[BIG],to[BIG],nxt[BIG],f[BIG],used[BIG],deg[BIG];
class question{
public:
int u[3];
int lca;
private:
}q[BIG];
vector<int>point[BIG>>1];
inline void add(int x,int y){
nxt[++tot]=las[x];
las[x]=tot;
to[tot]=y;
++deg[y];
return;
}
inline int find(int x){
return f[x]==x?x:f[x]=find(f[x]);
}
inline void dfs(int now,int fa){
used[now]=1;
register int i,p,other;
for(i=0;i<(int)point[now].size();++i){
p=point[now][i];
for(register int j=0;j<=1;++j){
other=q[p].u[j];
if(other!=now)
if(used[other])
q[p].lca=find(other);
}
}
for(register int e=las[now];e;e=nxt[e])
dfs(to[e],now);
f[now]=fa;
return;
}
}
using namespace TARJAN;
namespace DATA{
inline void read(int &x){
char c;
while(c=getchar(),c>'9'||c<'0');
x=c-48;
while(c=getchar(),c>='0'&&c<='9')
x=(x<<1)+(x<<3)+c-48;
return;
}
int wr[51];
inline void write(ll x){
while(x)
wr[++wr[0]]=x%10,x/=10;
while(wr[0])
putchar(48+wr[wr[0]--]);
putchar('\n');
return;
}
};
using namespace DATA;
namespace WORK{
ll ans,mod=1ll;
inline void work(){
read(n);
FOR(i,1,n-1){
read(x);
read(y);
add(x,y);
}
FOR(i,1,n)
f[i]=i;
FOR(i,1,63)
mod<<=1;
read(m);
FOR(i,1,m){
read(q[i].u[0]);
read(q[i].u[1]);
point[q[i].u[0]].push_back(i);
point[q[i].u[1]].push_back(i);
}
FOR(i,1,n)
if(!deg[i]){
dfs(i,0);
break;
}
FOR(i,1,m){
ans=(ll)(ans*n+q[i].lca);
if(ans<0){
ans+=mod;
ans+=mod;
}
}
write(ans);
return;
}
};
using namespace WORK;
int main(){
work();
return 0;
}