zoukankan      html  css  js  c++  java
  • POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    题意分析

    给出n个点,m个询问,和当前位置pos。
    先给出n-1条边,u->v以及边权w。
    然后有m个询问,询问分2种:
    一是讲第i条边的边权修改为w。
    二是询问从当前位置走到点x经过的边权和(下次询问就是从这点开始)。

    边权的树链剖分,其实和点权的差不多。对于一条边u-v,及其边权w,在建立线段树的时候,将深度大的点,当做其边权w,如dep[u]>dep[v],就令newid[u] = w。这样一来,将边权问题转化为点权问题,需要注意的,就是在查询的时候,对于lca的处理。

    处理方法也很简单,首先判断:当深度大的网上爬,爬到一定程度的时候,是否两点已经重合,若是的话,直接返回值就好。 否则,就用查询[深度小的儿子]到[深度大的这段区间],并将结果累加到ans中。

    代码总览

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ll int
    #define nmax 100820
    using namespace std;
    int fa[nmax],son[nmax],sz[nmax],newid[nmax],hashback[nmax],dep[nmax],top[nmax];
    int num,tot,head[nmax];
    struct edge{
        int to;
        int next;
    }edg[nmax<<1];
    struct tree{
        int l,r,val;
        int mid(){
            return (l+r)>>1;
        }
    }tree[nmax<<2];
    struct mess{
        int u,v,w;
    }mes[nmax];
    void add(int u, int v){
        edg[tot].to = v;
        edg[tot].next = head[u];
        head[u] = tot++;
    }
    void dfsFirst(int rt, int f,int d){
        dep[rt] = d;
        fa[rt] = f;
        sz[rt] = 1;
        for(int i = head[rt]; i!= -1; i = edg[i].next){
            int nxt = edg[i].to;
            if(nxt != f){
                dfsFirst(nxt,rt,d+1);
                sz[rt]+=sz[nxt];
                if(son[rt] == -1 || sz[nxt] > sz[son[rt]]){
                    son[rt] = nxt;
                }
            }
    
        }
    }
    void dfsSecond(int rt, int tp){
        top[rt] = tp;
        newid[rt] = ++num;
        if(son[rt] == -1) return;
        dfsSecond(son[rt],tp);
        for(int i = head[rt];i != -1; i = edg[i].next){
            int nxt = edg[i].to;
            if(nxt != son[rt] && nxt != fa[rt])
                dfsSecond(nxt,nxt);
        }
    }
    void init(){
        memset(tree,0,sizeof tree);
        memset(head,-1,sizeof head);
        memset(son,-1,sizeof son);
        memset(edg,0,sizeof edg);
        tot = num = 0;
    }
    void PushUp(int rt){
        tree[rt].val = tree[rt<<1].val + tree[rt<<1|1].val;
    }
    void Build(int l, int r, int rt){
        tree[rt].l = l; tree[rt].r = r;
        if(l == r){
            return;
        }
        Build(l,tree[rt].mid(),rt<<1);
        Build(tree[rt].mid()+1,r,rt<<1|1);
        PushUp(rt);
    }
    void UpdatePoint(int val, int pos, int rt){
        if(tree[rt].l == tree[rt].r){
            tree[rt].val = val ;
            return;
        }
        if(pos <= tree[rt].mid()) UpdatePoint(val,pos,rt<<1);
        else UpdatePoint(val,pos,rt<<1|1);
        PushUp(rt);
    }
    int QuerySUM(int l,int r,int rt)
    {;
        if(l>tree[rt].r || r<tree[rt].l) return 0;
        if(l <= tree[rt].l && tree[rt].r <= r) return tree[rt].val;
        return QuerySUM(l,r,rt<<1) + QuerySUM(l,r,rt<<1|1);
    }
    long long  Find_SUM(int x, int y){
        int tx = top[x],ty =top[y];
        long long ans  = 0;
        while(tx != ty){
            if(dep[tx] < dep[ty]){
                swap(x,y);
                swap(tx,ty);
            }
            ans += QuerySUM(newid[tx],newid[x],1);
            x = fa[tx]; tx = top[x];
        }
        if(x == y) return ans;
        if(dep[x] > dep[y]) swap(x,y);
        ans += QuerySUM(newid[son[x]],newid[y],1);
        return ans;
    }
    
    int n,m;
    int main()
    {
    //    freopen("in.txt","r",stdin);
        int m,x,y,posnow;
        int op;
        while(scanf("%d %d %d",&n,&m,&posnow)!=EOF){
            init();
            for(int i =1;i<=n-1;++i){
                scanf("%d %d %d",&mes[i].u,&mes[i].v,&mes[i].w);
                add(mes[i].u,mes[i].v);
                add(mes[i].v,mes[i].u);
            }
            num = 0;
            dfsFirst(1,0,1);
            dfsSecond(1,1);
            Build(1,n,1);
            for(int i = 1;i<=n-1;++i){
                if(dep[mes[i].u] > dep[mes[i].v])// v is bigger;
                    swap(mes[i].u,mes[i].v);
                UpdatePoint(mes[i].w,newid[mes[i].v],1);
    
            }
    //        printf("MESSA ID    DATA   FA   SON   SIZE   DEEP   NEWID  TOP  SEGHASH
    ");
    //        for(int i = 1;i<=n;++i){
    //            printf("DEBUG %5d %5d %5d %5d %5d %5d %5d %5d %5d
    ",i,data[i],fa[i],son[i],sz[i],dep[i],newid[i],top[i],seghash[i]);
    //        }
    //
    //        printf("MESSA ID   val
    ");
    //        for(int i = 1;i<=n;++i){
    //            printf("DEBUF %d   %d
    ",i,QuerySUM(i,i,1));
    //        }
            for(int i = 0;i<m;++i){
                scanf("%d",&op);
                if(op == 1){//change
                    scanf("%d %d",&x,&y);
                    x = newid[mes[x].v];
                    UpdatePoint(y,x,1);
                }else {//ask
                    scanf("%d",&x);
                    printf("%lld
    ",Find_SUM(posnow,x));
                    posnow = x;
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    快速幂模板
    部分有关素数的题
    POJ 3624 Charm Bracelet (01背包)
    51Nod 1085 背包问题 (01背包)
    POJ 1789 Truck History (Kruskal 最小生成树)
    HDU 1996 汉诺塔VI
    HDU 2511 汉诺塔X
    HDU 2175 汉诺塔IX (递推)
    HDU 2077 汉诺塔IV (递推)
    HDU 2064 汉诺塔III (递推)
  • 原文地址:https://www.cnblogs.com/pengwill/p/7367014.html
Copyright © 2011-2022 走看看