1. 程式人生 > >Company CodeForces - 1062E

Company CodeForces - 1062E

http://codeforces.com/problemset/problem/1062/E

[l,r]內決定lca的肯定是dfs序最小和最大的兩個點 因為一棵子樹的dfs序是連續的 線段樹維護一下每個點dfs序的最大次大和最小次小即可 看刪最小合適還是刪最大合適

比賽時水題切的太慢了 根本沒看見這個題 菜的一批

 

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int N=0x3f3f3f3f;

struct node
{
    int v,next;
};

node edge[2*maxn];
int dp[maxn][20];
int maxx[4*maxn],idmax[4*maxn],minn[4*maxn],idmin[4*maxn];
int first[maxn],deep[maxn],mp[maxn];
int n,q,num;

void addedge(int u,int v)
{
    edge[num].v=v;
    edge[num].next=first[u];
    first[u]=num++;
}

void dfs(int cur,int fa)
{
    int i,v;
    mp[cur]=++num;
    for(i=first[cur];i!=-1;i=edge[i].next){
        v=edge[i].v;
        if(v!=fa){
            dp[v][0]=cur,deep[v]=deep[cur]+1;
            dfs(v,cur);
        }
    }
}

void solve()
{
    int i,j;
    dp[1][0]=0,deep[1]=0;
    dfs(1,0);
    for(j=1;(1<<j)<=n;j++){
        for(i=1;i<=n;i++){
            dp[i][j]=dp[dp[i][j-1]][j-1];
        }
    }
}

int getlca(int u,int v)
{
    int i;
    if(deep[u]<deep[v]) swap(u,v);
    for(i=log2(n);i>=0;i--){
        if(deep[dp[u][i]]>=deep[v]) u=dp[u][i];
    }
    if(u==v) return u;
    for(i=log2(n);i>=0;i--){
        if(dp[u][i]!=dp[v][i]) u=dp[u][i],v=dp[v][i];
    }
    return dp[u][0];
}

void pushup(int cur)
{
    if(maxx[2*cur]>maxx[2*cur+1]){
        maxx[cur]=maxx[2*cur];
        idmax[cur]=idmax[2*cur];
    }
    else{
        maxx[cur]=maxx[2*cur+1];
        idmax[cur]=idmax[2*cur+1];
    }
    if(minn[2*cur]<minn[2*cur+1]){
        minn[cur]=minn[2*cur];
        idmin[cur]=idmin[2*cur];
    }
    else{
        minn[cur]=minn[2*cur+1];
        idmin[cur]=idmin[2*cur+1];
    }
}

void build(int l,int r,int cur)
{
    int m;
    if(l==r){
        maxx[cur]=minn[cur]=mp[l];
        idmax[cur]=idmin[cur]=l;
        return;
    }
    m=(l+r)/2;
    build(l,m,2*cur);
    build(m+1,r,2*cur+1);
    pushup(cur);
}

void update(int tar,int val,int l,int r,int cur)
{
    int m;
    if(l==r){
        maxx[cur]=minn[cur]=val;
        return;
    }
    m=(l+r)/2;
    if(tar<=m) update(tar,val,l,m,2*cur);
    else update(tar,val,m+1,r,2*cur+1);
    pushup(cur);
}

void query(int tp,int &res,int &val,int pl,int pr,int l,int r,int cur)
{
    int m;
    if(pl<=l&&r<=pr){
        if(tp==0){
            if(val>minn[cur]){
                val=minn[cur];
                res=idmin[cur];
            }
        }
        else{
            if(val<maxx[cur]){
                val=maxx[cur];
                res=idmax[cur];
            }
        }
        return;
    }
    m=(l+r)/2;
    if(pl<=m) query(tp,res,val,pl,pr,l,m,2*cur);
    if(pr>m) query(tp,res,val,pl,pr,m+1,r,2*cur+1);
}

int main()
{
    int i,l,r,u,v,p,val,res,ans1,ans2;
    scanf("%d%d",&n,&q);
    memset(first,-1,sizeof(first));
    num=0;
    for(i=2;i<=n;i++){
        scanf("%d",&p);
        addedge(p,i),addedge(i,p);
    }
    num=0;
    solve();
    build(1,n,1);
    while(q--){
        scanf("%d%d",&l,&r);
        ans2=-1;

        val=N;
        query(0,u,val,l,r,1,n,1);//minn
        val=-N;
        query(1,p,val,l,r,1,n,1);
        update(p,-N,1,n,1);
        val=-N;
        query(1,v,val,l,r,1,n,1);//cmaxx
        update(p,mp[p],1,n,1);
        res=deep[getlca(u,v)];
        if(ans2<res){
            ans1=p,ans2=res;
        }

        val=-N;
        query(1,u,val,l,r,1,n,1);//maxx
        val=N;
        query(0,p,val,l,r,1,n,1);
        update(p,N,1,n,1);
        val=N;
        query(0,v,val,l,r,1,n,1);//cminn
        update(p,mp[p],1,n,1);
        res=deep[getlca(u,v)];
        if(ans2<res){
            ans1=p,ans2=res;
        }
        printf("%d %d\n",ans1,ans2);
    }
    return 0;
}

/*
6 2
1 2 1 2 4
2 3
1 4
*/