HDU 3078 (LCA+树链第K大)

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=3078

题目大意:定点修改。查询树中任意一条树链上,第K大值。

解题思路

先用离线Tarjan把每个Query树链的LCA求出来。

LCA中对连接树Dfs的时候,令p[v]=u,记录v的前驱。

LCA结束后,对于每个Query:

从u开始回溯到LCA,记录值。从v开始回溯到LCA,记录值。

再加上LCA这个点的值,形成一条完整树链。特判树链长度是否小于K。

对树链中的值,从大到小排序,取第K大即可。

#include "cstdio"

#include "cstring"

#include "vector"

#include "algorithm"

using namespace std;

#define maxn 80005

int head[maxn],qhead[maxn],lag[maxn],kth[maxn],tot1,tot2,f[maxn],vis[maxn],ancestor[maxn],p[maxn];

bool cmp(int a,int b) {return a>b;}

struct Edge

{

    int to,next;

}e[maxn*2];

struct Query

{

    int from,to,next,idx;

}q[maxn*2];

void addedge(int u,int v)

{

    e[tot1].to=v;

    e[tot1].next=head[u];

    head[u]=tot1++;

}

void addquery(int u,int v,int idx)

{

    q[tot2].from=u;

    q[tot2].to=v;

    q[tot2].next=qhead[u];

    q[tot2].idx=idx;

    qhead[u]=tot2++;

}

int find(int x) {return x!=f[x]?f[x]=find(f[x]):x;}

void Union(int u,int v)

{

    u=find(u),v=find(v);

    if(u!=v) f[v]=u;

}

void LCA(int u)

{

    vis[u]=true;

    f[u]=u;

    for(int i=head[u];i!=-1;i=e[i].next)

    {

        int v=e[i].to;

        if(!vis[v])

        {

            p[v]=u;

            LCA(v);

            Union(u,v);

        }

    }

    for(int i=qhead[u];i!=-1;i=q[i].next)

    {

        int v=q[i].to;

        if(vis[v]) ancestor[q[i].idx]=find(v);

        //or storage e[i].lca=e[i^1].lca=find(v)

    }

}

int main()

{

    //freopen("in.txt","r",stdin);

    int T,n,m,u,v,c,cmd;

    scanf("%d%d",&n,&m);

    tot1=tot2=0;

    memset(head,-1,sizeof(head));

    memset(qhead,-1,sizeof(qhead));

    memset(vis,0,sizeof(vis));

    for(int i=1;i<=n;i++) scanf("%d",&lag[i]);

    for(int i=0; i<n-1; i++)

    {

        scanf("%d%d",&u,&v);

        addedge(u,v);

        addedge(v,u);

    }

    for(int i=0; i<m; i++)

    {

        scanf("%d%d%d",&cmd,&u,&v);

        if(cmd==0) lag[u]=v;

        else

        {

            addquery(u,v,i);

            addquery(v,u,i);

            kth[i]=cmd;

        }

    }

    LCA(1);

    for(int i=0; i<tot2; i=i+2)

    {

        int u=q[i].from,v=q[i].to,idx=q[i].idx;

        int ed=ancestor[idx];

        vector<int> chain;

        while(u!=ed) chain.push_back(lag[u]),u=p[u];

        while(v!=ed) chain.push_back(lag[v]),v=p[v];

        chain.push_back(lag[ed]);

        if(chain.size()<kth[idx]) {printf("invalid request!\n");continue;}

        else

        {

            sort(chain.begin(),chain.end(),cmp);

            printf("%d\n",chain[kth[idx]-1]);

        }

    }

}

 

你可能感兴趣的:(HDU)