BZOJ4539: [Hnoi2016]树

日妈倍增LCA上面的Dep>打成>=
直接变成单次询问 O(n2) LCA
MDZZ

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
char c;

#define ll long long
const
 ll MaxC=1000000;
ll    rT=1000001,rC=1000001;
inline void read(ll&a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}
struct Chain{ll u,len;Chain *next;}*Head[100001],*Head2[100001],*Cach;
inline Chain *New(){if(rC>MaxC)Cach=new Chain[MaxC],rT=0;return Cach+rT++;}
inline void Add(ll v,ll u){Chain *tp=new Chain;tp->next=Head[v];Head[v]=tp;tp->u=u;}
inline void Add2(ll v,ll u,ll len){Chain *tp=new Chain;tp->len=len;tp->next=Head2[v];Head2[v]=tp;tp->u=u;}
ll dfsb[100001],dfse[100001],F1[100001][18],Dep[100001],Nod[100001];
ll Cur;
ll Cnt;

inline ll  Dis1(ll l,ll r)
{
    ll j,o=l,O=r;
    if(Dep[l]<Dep[r])swap(l,r);
    while(Dep[l]^Dep[r])
    {
        for(j=0;Dep[F1[l][j+1]]>Dep[r];j++)
        Cnt++;
        l=F1[l][j];
    }
    while(l^r)
    {
        for(j=0;F1[l][j+1]!=F1[r][j+1];j++)
        Cnt++;
        l=F1[l][j],r=F1[r][j];
    }
    return Dep[o]+Dep[O]-2*Dep[l];
}

struct Node
{
    ll l,r,sum;
    Node *lc,*rc;
}*T[1000001],*Cache;
int ttt;
Node *Neww(){if(rT>MaxC)Cache=new Node[MaxC],rT=0;return Cache+rT++;}

Node *Empty(ll l,ll r){Node *T=Neww();T->l=l,T->r=r,T->sum=0;T->lc=T->rc=NULL;return T;}
Node *Modify(Node*Old,ll l)
{
    Cnt++;
    if(Old->l==Old->r)
    {
       Node *C=Empty(Old->l,Old->r);
       C->sum++;
       return C;
    }
    else
    {
      Node *New=Neww();
      *New=*Old;
      ll Mid=Old->l+Old->r>>1;
      if(Old->lc==NULL)
        New->lc=Empty(Old->l,Mid),New->rc=Empty(Mid+1,Old->r);
       New->sum++;
       if(l<=Mid)New->lc=Modify(New->lc,l);
       else New->rc=Modify(New->rc,l);
       return New;
     }
}
ll noi;
ll Query(Node *Old,Node *New,ll k)
{
    Cnt++;
    if(New->l==New->r)return New->l;
    if(New->lc->sum-(Old->lc?Old->lc->sum:0)>=k)
    return Query(Old->lc?Old->lc:Old,New->lc,k);
    return Query(Old->rc?Old->rc:Old,New->rc,k-(New->lc->sum-(Old->lc?Old->lc->sum:0)));
}

void dfs(ll u,ll f)
{
    F1[u][0]=f;
    for(ll j=1;j<=17;j++)
        F1[u][j]=F1[F1[u][j-1]][j-1];
    Dep[u]=Dep[f]+1;
    Nod[dfsb[u]=++Cur]=u;
    T[Cur]=Modify(T[Cur-1],u);
    for(Chain *tp=Head[u];tp;tp=tp->next)
        if(tp->u!=f)dfs(tp->u,u);
    dfse[u]=Cur;
}

ll Dep2[400001],F2[400001][18],Dis[400001];

ll   In[400001],NoN[400001];
ll LCA2(ll l,ll r)
{
    ll j;
    if(Dep2[l]<Dep2[r])swap(l,r);
    while(Dep2[l]^Dep2[r])
    {
        for(j=0;Dep2[F2[l][j+1]]>Dep2[r];j++);
        l=F2[l][j];
    }
    while(l^r)
    {
        for(j=0;F2[l][j+1]!=F2[r][j+1];j++);
        l=F2[l][j],r=F2[r][j];
    }
   return l;
}

ll Val;

ll To(ll u,ll Height)
{   
  ll O=u,j;
  while(Dep2[u]^Height)
    {
        for(j=0;Dep2[F2[u][j+1]]>=Height;j++);
        u=F2[u][j];
    }
   Val=Dis[O]-Dis[u];
   return u;
}
void dfs2(ll u,ll f)
{
    F2[u][0]=f;
    for(ll j=1;j<=17;j++)
        F2[u][j]=F2[F2[u][j-1]][j-1];
    Dep2[u]=Dep2[f]+1;
    for(Chain *tp=Head2[u];tp;tp=tp->next)
        if(tp->u!=f)Dis[tp->u]=Dis[u]+tp->len,dfs2(tp->u,u);
}
struct L
{
    ll No;
    ll l,r;
    ll Oldl;
}Q[1000001];
ll Con; 

ll find(ll j)
{
    ll mid,l=1,r=Con;
    while(l<r)
    {
        Cnt++;
        mid=l+r>>1;
        if(Q[mid].r<j)l=mid+1;
        else r=mid;
    }
  return r;
}



ll n,m;
ll Cn;


inline ll Dis2(ll u,ll v)
{
    if(u==35&&v==34)
      u++,u--;
    ll a=find(u),b=find(v);
    ll lOl=Query(T[Q[a].Oldl-1],T[Q[a].Oldl+Q[a].r-Q[a].l],u-Q[a].l+1);
    ll rOl=Query(T[Q[b].Oldl-1],T[Q[b].Oldl+Q[b].r-Q[b].l],v-Q[b].l+1); 
    ll l=Q[a].No,r=Q[b].No;
    ll ans=0,j,o=l,O=r;
    if(Dis[l]>Dis[r])swap(l,r),swap(lOl,rOl),swap(a,b),swap(o,O);
    ll L=LCA2(l,r);
    if(l==r)
    {
       return Dis1(lOl,rOl);
    }

    if(l==L)
    {
        r=To(r,Dep2[L]+1);
        ans+=Val;
        ans+=Dis1(rOl,Nod[Q[b].Oldl]);
        ans+=Dis1(lOl,In[r])+1;
        return ans;
    }
    else
    {
      ans+=Dis1(rOl,Nod[Q[b].Oldl]);
      ans+=Dis1(lOl,Nod[Q[a].Oldl]);
      l=To(l,Dep2[L]+1);
      ans+=Val;
      r=To(r,Dep2[L]+1);    
      ans+=Val;
      ans+=Dis1(In[l],In[r])+2;
      return ans;
    }
}


int  main()
{

    ll i,j,k;   ll q;
    read(n),read(m),read(q);
    *T=Empty(1,n);
    for(i=1;i<n;i++)
        read(k),read(j),Add(k,j),Add(j,k);
    dfs(1,1);
    Q[++Con]=(L){1,1,Cur,1};
    Cn=1;
    ll M=Cur;
    for(ll i=1;i<=m;i++)
    {
        ll a,b,c;
        read(a),read(b);c=find(b);
        b=Query(T[Q[c].Oldl-1],T[Q[c].Oldl+Q[c].r-Q[c].l],b-Q[c].l+1);
        In[Cn+1]=b;
          Add2(Q[c].No,Cn+1,1+Dis1(b,Nod[Q[c].Oldl])); 
        Q[++Con]=(L){++Cn,Cur+1,Cur+1+dfse[a]-dfsb[a],dfsb[a]},NoN[Cn]=Con; 
     Cur+=dfse[a]-dfsb[a]+1;
    }
    dfs2(1,1);
    for(ll i=1;i<=q;i++)
    {
        ll u,v,a,b,ans=0;
        read(u),read(v);
        ans=Dis2(u,v);
        printf("%lld\n",ans);
    }
    return 0;
}

你可能感兴趣的:(BZOJ4539: [Hnoi2016]树)