数据结构____倍增+线段树 HDU5256 pog loves szh III

HDU 5256 pog loves szh III

题解:
1.用bfs建立层级数组、倍增数组
2.倍增法求LCA 传送门
3.线段树的ST表实现,求一段区间的LCA

AC code

#include<bits/stdc++.h>

using namespace std;

const int maxn = 3e5+1000;
const int DEG = 20;

int n;

int head[maxn];
int f[maxn][20];
int st[maxn][20];
int dep[maxn];
int tot;
struct edge
{
  int to,next;
}es[maxn<<1];

void add_edge(int u, int v)
{
    es[tot].to = v;
    es[tot].next = head[u];
    head[u] = tot++;
}

void bfs(int root)
{
  f[root][0] = root;
  dep[root] = 0;
  queue<int> q;
  q.push(root);
  while(!q.empty())
  { 
     int u = q.front();
     q.pop();
     for(int i = 1; i < DEG; i++)
	   f[u][i] = f[f[u][i-1]][i-1];
     for(int i = head[u]; i != -1; i = es[i].next)
     {
	     int v = es[i].to;
	     if(f[u][0] == v) continue;
	     f[v][0] = u;
	     dep[v] = dep[u]+1;
	     q.push(v);
     }
  }
}

int LCA(int u,int v)
{
   if(dep[u] < dep[v])  swap(u,v);
   for(int det = dep[u]-dep[v], i = 0; det ; det >>= 1, i++)
	   if(det & 1)    u = f[u][i];
   if(u == v) return u;
   for(int i = DEG-1; i >= 0; i--)
	   if(f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
   return f[u][0];
}

int main()
{
   while(scanf("%d",&n) != EOF)
   {
      tot = 0;
      memset(head,-1,sizeof(head));
      memset(f,-1,sizeof(f));
      int u,v;
      for(int i = 0; i < n-1; i++)
      {
	  scanf("%d%d",&u,&v);
	  add_edge(u,v);
	  add_edge(v,u);
      }
      bfs(1);
      for(int i = 1; i <= n; i++)  st[i][0] = i;
      for(int j = 1; j < 20; j++)
	     for(int i = 1; i+ (1<<(j-1)) <= n; i++)
		    st[i][j] = LCA(st[i][j-1],st[i+(1<<(j-1))][j-1]);
     int q;
     scanf("%d",&q);
     int l,r;
     while(q--)
     {
	     scanf("%d%d",&l,&r);
	     int k = log2(r-l+1);
	     int ans = LCA(st[l][k],st[r-(1<<k)+1][k]);
	     printf("%d\n",ans);
     }
   }
   return 0;
 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值