hdu 5266 pog loves szh III 在线lca+线段树区间优化

题目链接:hdu 5266 pog loves szh III

思路:因为它查询的是区间上的lca,所以我们需要用在线lca来处理,达到单点查询的复杂度为O(1),所以我们在建立线段树区间查询的时候可以达到O(1*nlgn)的时间复杂度

ps:因为栈很容易爆,所以。。。。。你懂的 --》#pragma comment(linker, "/STACK:1024000000,1024000000")

/**************************************************************
    Problem:hdu 5266
    User: youmi
    Language: C++
    Result: Accepted
    Time:3790Ms
    Memory:82816k
****************************************************************/
#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <sstream>
#include <cmath>
#include <queue>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define rep(i,n) for(int i=0;i<n;i++)
#define lson (step<<1)
#define rson (lson+1)
#define esp 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl

using namespace std;
typedef long long ll;
int n,q;
const int M=20;
int bit[M];
const int maxn=300000+10;
struct side
{
    int v,next;
}e[maxn<<1];
struct node
{
    int l,r,fa;
}seg[maxn<<2];

int head[maxn],euler[maxn<<1],pos[maxn],depth[maxn<<1],vis[maxn];
int dp[maxn<<1][M];
int T,tot;
void  Swap(int &a,int &b)
{
    int c;
    c=a;
    a=b;
    b=c;
}
void ebuild(int u,int v)
{
    e[T].v=v;
    e[T].next=head[u];
    head[u]=T++;
}
void  dfs(int u,int dep)
{
    vis[u]=1;
    euler[++tot]=u;
    depth[tot]=dep;
    pos[u]=tot;
    for(int i=head[u];~i;i=e[i].next)
    {
        int v=e[i].v;
        if(!vis[v])
        {
            dfs(v,dep+1);
            euler[++tot]=u;
            depth[tot]=dep;
        }
    }
}
void ST(int len)
{
    for(int i=1;i<=len;i++)
        dp[i][0]=i;
    int k=(int )(log(len*1.0)/log(2.0));
    for(int j=1;j<=k;j++)
    {
        for(int i=1;i+bit[j]<=len;i++)
        {
            int l=dp[i][j-1];
            int r=dp[i+bit[j-1]][j-1];
            dp[i][j]=depth[l]<depth[r]?l:r;
        }
    }
}
int RMQ(int x,int y)
{
    int len=(y-x+1);
    int k=(int )(log(len*1.0)/log(2.0));
    int l=dp[x][k];
    int r=dp[y-bit[k]+1][k];
    return depth[l]<depth[r]?l:r;
}
int lca(int x,int y)
{
    int l=pos[x];
    int r=pos[y];
    if(l>r)
        Swap(l,r);
    return euler[RMQ(l,r)];
}
void pushup(int step)
{
    if(seg[lson].fa==seg[rson].fa)
        seg[step].fa=seg[lson].fa;
    else
    {
        seg[step].fa=lca(seg[lson].fa,seg[rson].fa);
    }
}
int query(int step,int l,int r)
{
    //printf("step->%d stepl->%d stepr->%d l->%d r->%d
",step,seg[step].l,seg[step].r,l,r);
    if(l==seg[step].l&&r==seg[step].r)
        return seg[step].fa;
    int mid=(seg[step].l+seg[step].r)>>1;
    if(mid>=r)
        return query(lson,l,r);
    else if(mid<l)
        return query(rson,l,r);
    else
    {
        return lca(query(lson,l,mid),query(rson,mid+1,r));
    }
}
void qbuild(int step,int l,int r)
{
    seg[step].l=l;
    seg[step].r=r;
    if(l==r)
    {
        seg[step].fa=l;
        return ;
    }
    int mid=(l+r)>>1;
    qbuild(lson,l,mid);
    qbuild(rson,mid+1,r);
    pushup(step);
}
void init()
{
    ones(head);
    zeros(vis);
    T=0;
    tot=0;
    int u,v;
    for(int i=0;i<n-1;i++)
    {
        scanf("%d%d",&u,&v);
        ebuild(u,v);
        ebuild(v,u);
    }
    dfs(1,1);
    ST(2*n-1);
    qbuild(1,1,n);
}
int main()
{
    //freopen("in.txt","r",stdin);
    for(int i=0;i<=M;i++)
        bit[i]=(1<<i);
    while(~sc(n))
    {
        init();
        sc(q);
        int l,r;
        while(q--)
        {
            sc2(l,r);
            printf("%d
",query(1,l,r));
        }
    }
    return 0;
}
不为失败找借口,只为成功找方法
原文地址:https://www.cnblogs.com/youmi/p/4574676.html