• poj 2763 求树上的两个节点的最短距离+在线修改答案


    题目链接: http://poj.org/problem?id=2763
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #define clr(x)memset(x,0,sizeof(x))
    #define maxn 200005
    struct node
    {
        int to,next,w,xu;
    }e[1000000];
    int tot;
    int head[maxn];
    void add(int s,int t,int wi,int xu)
    {
        e[tot].xu=xu;         //边的序号
        e[tot].w=wi;
        e[tot].to=t;
        e[tot].next=head[s];
        head[s]=tot++;
    }
    int dp[maxn<<1][18];
    int x[maxn<<1];
    int d[maxn];
    int r[maxn];
    int v[maxn];
    int f[maxn];
    int ll[maxn];
    int rr[maxn];
    int g[maxn];
    int n,m;
    int min(int i,int j)
    {
        return d[i]<d[j]?i:j;
    }
    void makermq(int nn)
    {
        int i,j;
        for(i=0;i<nn;i++)
            dp[i][0]=i;
        for(j=1;(1<<j)<=nn;j++)
            for(i=1;i+(1<<j)-1<nn;i++)
                dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    }
    int rmq(int l,int r)
    {
        int k=(int)(log((r-l+1)*1.0)/log(2.0));
        return min(dp[l][k],dp[r-(1<<k)+1][k]);
    }
    int cnt,ti;
    void dfs(int u,int deep)
    {
        v[u]=1;                   //标记节点是否被访问;
        x[cnt]=u;                  //cnt为标记访问点先后顺序的一个序列,x数组即表示当前访问的节点。
        d[cnt]=deep;               // d数组表示当前访问节点的深度。
        r[u]=cnt++;                // r 数组是表示本节点第一次出现在访问序列中的位置;
        ll[u]=++ti;             //第一次访问节点的时间戳
        int i,k;
        for(i=head[u];i;i=e[i].next)
        {
            k=e[i].to;
            if(!v[k])
            {
                g[e[i].xu]=k;
                dfs(k,deep+1);
                x[cnt]=u;              //回退时也要记录访问序列;
                d[cnt++]=deep;
            }
        }
        rr[u]=ti;        //第二次访问这个节点的时间戳
    }
    int tree[maxn];
    int lowbit(int x)
    {
        return (x)&(-x);
    }
    void update(int pos,int x)
    {
        while(pos<=n)
        {
            tree[pos]+=x;
            pos+=lowbit(pos);
        }
    }
    int sum(int pos)
    {
        int s=0;
        while(pos>0)
        {
            s+=tree[pos];
            pos-=lowbit(pos);
        }
        return s;
    }
    int edge[maxn];
    int val[maxn];
    int main()
    {
        int i,st;
        while(scanf("%d%d%d",&n,&m,&st)!=EOF)
        {
            int a,b,c;
            clr(head);  clr(v);
            clr(f);     clr(tree);
            tot=1;
            ti=-1;
            for(i=1;i<n;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                val[i]=c;
                edge[i]=c;
                add(a,b,c,i);
                add(b,a,c,i);
            }
            cnt=0;
            dfs(1,0);
            makermq(2*n-1);
            for(i=1;i<n;i++)
            {
                update(ll[g[i]],edge[i]);
                update(rr[g[i]]+1,-edge[i]);
            }
            int op;
            while(m--)
            {
                scanf("%d",&op);
                if(op==1)            //将树上的操作变成一个序列的操作。
                {
                    scanf("%d%d",&a,&b);
                    update(ll[g[a]],-val[a]);
                    update(rr[g[a]]+1,val[a]);
                    update(ll[g[a]],b);
                    update(rr[g[a]]+1,-b);
                    val[a]=b;
                }
                else
                {
                    scanf("%d",&a);
                    int lca,d1,d2,d3;
                    if(r[st]<=r[a])
                         lca=x[rmq(r[st],r[a])];
                    else lca=x[rmq(r[a],r[st])];
                    d1=sum(ll[st]);
                    d2=sum(ll[a]);
                    d3=sum(ll[lca]);
                    st=a;
                    printf("%d
    ",d1+d2-2*d3);
                }
            }
        }
        return 0;
    }
    
    
    
     
  • 相关阅读:
    bzoj 4897 天赋 有向图的矩阵数定理
    bzoj 4621 Tc605 思想+dp
    bzoj 4596 [Shoi2016]黑暗前的幻想乡 矩阵树定理+容斥
    bzoj 4455 [Zjoi2016]小星星 树形dp&容斥
    获取Android设备无线和以太网MAC地址
    Java WebSocket库:https://github.com/TooTallNate/Java-WebSocket
    UsbManager, UsbDevice的简单示例
    Android开发之开机自动启动应用
    使用Microsoft Office 2007将文档转换为PDF
    C/C++实现删除字符串的首尾空格
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9682819.html
Copyright © 2020-2023  润新知