zoukankan      html  css  js  c++  java
  • POJ 2763 (LCA +RMQ+树状数组 || 树链部分) 查询两点距离+修改边权

    题意: 知道了一颗有  n 个节点的树和树上每条边的权值,对应两种操作:

              0 x        输出 当前节点到 x节点的最短距离,并移动到 x 节点位置

              1 x val   把第 x 条边的权值改为 val

    题意: 知道了一颗有  n 个节点的树和树上每条边的权值,对应两种操作:

              0 x        输出 当前节点到 x节点的最短距离,并移动到 x 节点位置

              1 x val   把第 x 条边的权值改为 val

    LCA +RMQ+树状数组

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 2e5+100;
    
    int N,Q,S;
    //vector <int> G[maxn];
    
    struct edge{
        int to,next,w;
    }e[2*maxn];
    
    int head[2*maxn],tot;
    void add_edge(int u,int v,int w)
    {
        e[tot].to = v;
        e[tot].w = w;
        e[tot].next = head[u];
        head[u] = tot++;
    
        e[tot].to = u;
        e[tot].w = w;
        e[tot].next = head[v];
        head[v] = tot++;
    }
    
    int in[maxn],out[maxn],P[2*maxn],fa[maxn][30],dep[maxn],dis[maxn],cnt;
    void dfs(int u,int _fa,int _dep,int _dis)
    {
        in[u] = ++cnt;
        P[cnt] = u;
        fa[u][0] = _fa;
        dis[u] = _dis;
        dep[u] = _dep;
        for(int i=head[u];~i;i=e[i].next)
        {
            int v = e[i].to;
            if(v == _fa) continue;
            dfs(v,u,_dep+1,_dis+e[i].w);
        }
        out[u] = ++cnt;
    }
    void debug()
    {
        printf("in:	");for(int i=1;i<=N;i++) printf("%d ",in[i]);puts("");
        printf("out:	");for(int i=1;i<=N;i++) printf("%d ",out[i]);puts("");
        printf("p:	");for(int i=1;i<=cnt;i++) printf("%d ",P[i]);puts("");
        printf("dis:	");for(int i=1;i<=N;i++) printf("%d ",dis[i]);puts("");
        printf("dep:	");for(int i=1;i<=N;i++) printf("%d ",dep[i]);puts("");
        printf("edge:");for(int i=0;i<tot;i++) printf("	to:%d w:%d
    ",e[i].to,e[i].w);
    }
    
    int initLCA()
    {
        int m = (int)log(N)/log(2)+1;
        for(int k=0;k<m;k++)
        {
            for(int v=1;v<=N;v++)
            {
                if(fa[v][k] < 0) {fa[v][k+1] = -1;continue;}
                else fa[v][k+1] = fa[fa[v][k]][k];
            }
        }
    }
    
    int LCA(int u,int v)
    {
        int m = (int)log(N)/log(2)+1;
        if(dep[v] > dep[u]) swap(u,v);
        for(int k=0;k<m;k++)
        {
            if((dep[u]-dep[v])>>k & 1 )
                u = fa[u][k];
        }
        if(u == v) return u;
        for(int k=m-1;k>=0;k--)
        {
            if(fa[u][k] != fa[v][k])
            {
                u = fa[u][k];
                v = fa[v][k];
            }
        }
        return fa[u][0];
    }
    
    int c[2*maxn];
    int lowbit(int x) {return x&-x;}
    
    void init()
    {
        memset(head,-1,sizeof head);
        memset(fa,-1,sizeof fa);
        memset(c,0,sizeof c);
        memset(in,0,sizeof in);
        memset(out,0,sizeof out);
        tot = 0;
        cnt = 0;
    }
    
    void add(int x,int d)
    {
        while(x)
        {
            c[x] += d;
            x -= lowbit(x);
        }
    }
    void add_seg(int l,int r,int d)
    {
        add(r,d);
        add(l-1,-d);
    }
    int sum(int x)
    {
        int res = 0;
        //printf("u:%d ",P[x]);
        while(x <= cnt)
        {
            res += c[x];
            x += lowbit(x);
        }
        //printf("res:%d
    ",res);
        return res;
    }
    int dist(int x)
    {
        if(x == -1) return 0;
        return sum(in[x]) + dis[x];
    }
    int main()
    {
        //freopen("input.txt","r",stdin);
        while(~scanf("%d%d%d",&N,&Q,&S))
        {
            init();
            for(int i=0,u,v,w;i<N-1;i++)
            {
                scanf("%d%d%d",&u,&v,&w);
                add_edge(u,v,w);
            }
            dfs(1,-1,1,0);
            //debug();
            initLCA();
            for(int i=0;i<tot;i+=2)
            {
                if(dep[e[i].to] < dep[e[i+1].to]) swap(e[i].to,e[i+1].to);
            }
            int op;
            for(int i=0,a,b,c;i<Q;i++)
            {
                scanf("%d",&op);
                if(op == 0)
                {
                    scanf("%d",&a);
                    int lca = LCA(S,a);
                    //printf("lca:%d
    ",lca);
    
                    printf("%d
    ",dist(S)+dist(a)-2*(dist(lca)));
                    S = a;
                }else
                {
                    scanf("%d%d",&a,&b);
                    a--;
                    int u = e[a*2].to;
                    int dw = b - (dist(u) - dist(fa[u][0]));
                    //printf("dw:%d u:%d
    ",dw,u);
                    add_seg(in[u],out[u],dw);
                }
            }
        }
    }
    View Code

    树链部分

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    using namespace std;
    typedef long long ll;
    const int MAXN = 2e5 + 10;
    int n, q, s;
    int fa[MAXN]; // fa[v]: v 的父亲
    int dep[MAXN]; // dep[v]: v 的深度(根深度为1)
    int siz[MAXN]; // : 以 v 为根的子树的节点数
    int son[MAXN]; // : 重儿子,siz[u] 为 v 的子节点中 siz 值最大的,那么 u 就是 v 的重儿子
    int top[MAXN]; // : 表示 v 所在的重链的顶端节点
    int w[MAXN]; // : 表示 v 与其父亲节点的连边在线段树中的位置
    int num; // 将树映射到线段树上的标号
    int cnt, head[MAXN];
    struct Edge {
        int to, next;
    }edge[MAXN];
    struct E {
        int u, v, c;
    }e[MAXN];
    void addedge(int u, int v) {
        edge[cnt].to = v;
        edge[cnt].next = head[u];
        head[u] = cnt++;
    }
    void dfs(int u) {
        siz[u] = 1; son[u] = 0;
        for(int i = head[u]; ~i; i = edge[i].next) {
            if(edge[i].to != fa[u]) {
                fa[edge[i].to] = u;
                dep[edge[i].to] = dep[u] + 1;
                dfs(edge[i].to);
                if(siz[edge[i].to] > siz[son[u]]) son[u] = edge[i].to;
                siz[u] += siz[edge[i].to];
            }
        }
    }
    void build_tree(int u, int tp) {
        w[u] = ++num; top[u] = tp;
        if(son[u]) build_tree(son[u], top[u]); // 使重链各边在线段树中呈连续分布
        for(int i = head[u]; ~i; i = edge[i].next) {
            int v = edge[i].to;
            if(v != son[u] && v != fa[u])
                build_tree(v, v);
        }
    }
    ll sum[MAXN];
    void pushUp(int rt) {
        sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    }
    void build(int l, int r, int rt) {
        sum[rt] = 0;
        if(l == r) return;
        int m = (l + r) / 2;
        build(lson); build(rson);
    }
    void update(int p, int c, int l, int r, int rt) {
        if(l == r) {
            sum[rt] = c;
            return;
        }
        int m = (l + r) / 2;
        if(m >= p) update(p, c, lson);
        else update(p, c, rson);
        pushUp(rt);
    }
    ll query(int L, int R, int l, int r, int rt) {
        if(L <= l && R >= r) return sum[rt];
        int m = (l + r) / 2;
        ll res = 0;
        if(m >= L) res += query(L, R, lson);
        if(m < R) res += query(L, R, rson);
        return res;
    }
    void change(int v, int c) {
        if(dep[e[v].u] > dep[e[v].v]) update(w[e[v].u], c, 1, n, 1);
        else update(w[e[v].v], c, 1, n, 1);
    }
    ll seek(int v, int u) {
        int t1 = top[v], t2 = top[u];
        ll res = 0;
        while(t1 != t2) {
            if(dep[t1] < dep[t2]) {
                swap(t1, t2); swap(v, u);
            }
            res += query(w[t1], w[v], 1, n, 1);
            v = fa[t1]; t1 = top[v];
        }
        if(v == u) return res;
        if(dep[v] > dep[u]) swap(v, u);
        return res + query(w[son[v]], w[u], 1, n, 1);
    }
    int main() {
        memset(head, -1, sizeof head);
        cnt = num = 0;
        scanf("%d%d%d", &n, &q, &s);
        for(int i = 1;  i < n; i++) {
            scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].c);
            addedge(e[i].u, e[i].v);
            addedge(e[i].v, e[i].u);
        }
        dfs(1);
        build_tree(1, 1);
        build(1, n, 1);
        for(int i = 1; i < n; i++) {
            if(dep[e[i].u] > dep[e[i].v]) update(w[e[i].u], e[i].c, 1, n, 1);
            else update(w[e[i].v], e[i].c, 1, n, 1);
        }
        while(q--) {
            int cc;
            int x, y;
            scanf("%d", &cc);
            if(cc) {
                scanf("%d%d", &x, &y);
                change(x, y);
            } else {
                scanf("%d", &x);
                printf("%lld
    ", seek(s, x));
                s = x;
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    初始化mysql数据库 /usr/bin/mysql_install_db执行时报错
    CentOS7安装mysql兼容性问题
    CentOS7网络连接问题以及重启网络服务失败
    CentOS7安装nginx
    zookeeper启动时报错:Error contacting service. It is probably not running问题
    CentOS查看卸载openjdk
    使用yum命令时提示:Another app is currently holding the yum lock
    修改eclipse中文件打开默认方式
    [程序员代码面试指南]链表问题-单链表的选择排序(选择排序)
    [程序员代码面试指南]链表问题-删除无序链表中重复出现的节点
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/10439821.html
Copyright © 2011-2022 走看看