您的位置:首页 > 其它

hdu 5266 pog loves szh III(LCA)

2015-06-09 12:11 357 查看
题意:求编号l-r的lca。

做法:第一种方法是维护一个类似rmq的东西,因为abcd的lca,可以由ab的lca和cd的lca的lca得到,然后重叠也没有关系,就比如刚才的例子,abcd的lca也可以由abc的lca和bcd的lca的lca得到,所以我们用类似rmq的查询的就可以了。查询2个点的lca写的是树上倍增。

第二种方法比较容易想到,就是先dfs一遍找出欧拉序列,然后再rmq预处理一遍,因为2个点的lca就是欧拉序列中2点之间深度最浅的位置,同时还要rmq预处理那些编号在欧拉序列中的位置区间最小最大值。这样对于一个查询来说我们找出在欧拉序列中最小及最大的位置,再查lca即可。处理出欧拉序列再rmq内存用的真心多。。

AC代码1:

#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<string.h>
#include<string>
#include<sstream>
#include<bitset>
using namespace std;
#define ll __int64
#define ull unsigned __int64
#define eps 1e-8
#define NMAX 30000
#define MOD 1000000007
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1)
template<class T>
inline void scan_d(T &ret)
{
char c;
int flag = 0;
ret=0;
while(((c=getchar())<'0'||c>'9')&&c!='-');
if(c == '-')
{
flag = 1;
c = getchar();
}
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
if(flag) ret = -ret;
}
const int maxn = 3e5+5;
struct Edge
{
int v,next;
}e[maxn<<1];
int head[maxn],nct;

void add_edge(int u, int v)
{
e[nct].v = v; e[nct].next = head[u];
head[u] = nct++;
}
int _log[maxn*2],tot;

int euler[maxn*2],depth[maxn],pos[maxn];

void dfs(int u, int fa, int dep)
{
pos[u] = ++tot;
euler[tot] = u;
depth[u] = dep;
for(int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].v;
if(v == fa) continue;
dfs(v,u,dep+1);
euler[++tot] = u;
}
}

int lca[maxn*2][20];
int mi[maxn][20],mx[maxn][20];
void init(int n)
{
for(int i = 1; i <= 2*n-1; i++)
lca[i][0] = euler[i];
for(int j = 1; j <= _log[2*n-1]; j++)
for(int i = 1; i+(1<<j)-1 <= 2*n-1; i++)
{
if(depth[lca[i][j-1]] < depth[lca[i+(1<<(j-1))][j-1]]) lca[i][j] = lca[i][j-1];
else lca[i][j] = lca[i+(1<<(j-1))][j-1];
}
for(int i = 1; i <= n; i++) mi[i][0] = mx[i][0] = pos[i];
for(int j = 1; j <= _log
; j++)
for(int i = 1; i+(1<<j)-1 <= n; i++)
{
mi[i][j] = min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
mx[i][j] = max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
}
}

int getlca(int L, int R)
{
int k = _log[R-L+1];
if(depth[lca[L][k]] < depth[lca[R-(1<<k)+1][k]]) return lca[L][k];
return lca[R-(1<<k)+1][k];
}

int main()
{
#ifdef GLQ
freopen("input.txt","r",stdin);
// freopen("o.txt","r",stdin);
#endif
_log[1] = 0;
for(int i = 2; i <= 2*maxn; i++) if(i&(i-1)) _log[i] = _log[i-1]; else _log[i] = _log[i-1]+1;
int n;
while(~scanf("%d",&n))
{
memset(head,-1,sizeof(head));
nct = tot = 0;
for(int i = 1; i < n; i++)
{
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(1,1,1);
init(n);
int q;
scanf("%d",&q);
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
int k = _log[y-x+1];
int t1 = min(mi[x][k],mi[y-(1<<k)+1][k]),t2 = max(mx[x][k],mx[y-(1<<k)+1][k]);
printf("%d\n",getlca(t1,t2));
}
}
return 0;
}


AC代码2:
#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<string.h>
#include<string>
#include<sstream>
#include<bitset>
using namespace std;
#define ll __int64
#define ull unsigned __int64
#define eps 1e-8
#define NMAX 30000
#define MOD 1000000007
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1)
template<class T>
inline void scan_d(T &ret)
{
char c;
int flag = 0;
ret=0;
while(((c=getchar())<'0'||c>'9')&&c!='-');
if(c == '-')
{
flag = 1;
c = getchar();
}
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
if(flag) ret = -ret;
}
const int maxn = 3e5+10;
struct Edge
{
int v,next;
}e[maxn<<1];
int head[maxn],nct;

void add_edge(int u, int v)
{
e[nct].v = v; e[nct].next = head[u];
head[u] = nct++;
}
int father[maxn][20],depth[maxn];

void dfs(int u, int fa, int dep)
{
depth[u] = dep;
for(int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].v;
if(v == fa) continue;
father[v][0] = u;
dfs(v,u,dep+1);
}
}

int lca(int x, int y)
{
if(depth[x] < depth[y]) swap(x,y);
int k = depth[x]-depth[y];
for(int i = 0; i <= 19; i++) if(k&(1<<i))
x = father[x][i];
if(x == y) return x;
for(int i = 19; i >= 0; i--) if(father[x][i] != father[y][i])
{
x = father[x][i];
y = father[y][i];
}
return father[x][0];
}

int dp[maxn][20], _log[maxn];

int RMQ(int L, int R)
{
int k = _log[R-L+1];
return lca(dp[L][k],dp[R-(1<<k)+1][k]);
}

int main()
{
#ifdef GLQ
freopen("input.txt","r",stdin);
// freopen("o.txt","r",stdin);
#endif
_log[1] = 0;
for(int i = 2; i <= maxn; i++) if(i&(i-1)) _log[i] = _log[i-1]; else _log[i] = _log[i-1]+1;
int n;
while(~scanf("%d",&n))
{
memset(head,-1,sizeof(head));
nct = 0;
for(int i = 1; i < n; i++)
{
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(1,1,1);
for(int i = 1; i <= 19; i++)
for(int j = 1; j <= n; j++)
father[j][i] = father[father[j][i-1]][i-1];
for(int i = 1; i <= n; i++) dp[i][0] = i;
for(int j = 1; j <= _log
; j++)
for(int i = 1; i + (1<<j) - 1 <= n; i++)
dp[i][j] = lca(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
int q;
scanf("%d",&q);
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",RMQ(x,y));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: