zoukankan      html  css  js  c++  java
  • 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!
    ");continue;}
            else
            {
                sort(chain.begin(),chain.end(),cmp);
                printf("%d
    ",chain[kth[idx]-1]);
            }
        }
    }
  • 相关阅读:
    php xml解析方法
    phpmail 发送邮件失败
    善用Eclipse的代码模板功能
    php5.3 namespace
    MyEclipse6.5配置反编译插件
    程序bug致损失400亿,判程序员坐牢? 搞笑我们是认真的
    ios学习笔记(二)第一个应用程序--Hello World
    ios学习笔记(一)Windows7上使用VMWare搭建iPhone开发环境
    GJB150-2009军用装备实验室环境试验方法新版标准
    AXI总线简介
  • 原文地址:https://www.cnblogs.com/neopenx/p/4502708.html
Copyright © 2011-2022 走看看