• POJ 2763 Housewife Wind(树链剖分+线段树)


    题意:在一颗树上,你在s位置,询问s到x的距离,然后移动到x点,第二种操作是修改一条边的权值

    思路:直接树链剖分,不知道哪里出的bug,最后发现在主函数询问的时候好像有个标号改着改着改错了

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int maxn=500008;
    
    int n,m,s;
    int a[maxn],sz[maxn],dep[maxn],fa[maxn],top[maxn],son[maxn],head[maxn];
    int w[maxn],num,cnt;
    struct Edge
    {
        int to,next;
    };
    Edge v[maxn*2];
    void init()
    {
        num=0;cnt=0;
        memset(head,-1,sizeof(head));
    }
    void addedge(int x,int y)
    {
        v[cnt].to = y;
        v[cnt].next = head[x];
        head[x] = cnt++;
    }
    void dfs1(int u, int f, int d) {
        dep[u]=d;sz[u]=1;
        son[u]=0;fa[u]=f;
        for(int i=head[u];i!=-1;i = v[i].next){
            int to = v[i].to;
            if(to!=f){
                dfs1(to,u,d+1);
                sz[u]+=sz[to];
                if(sz[son[u]]<sz[to])son[u]=to;
            }
        }
    }
    void dfs2(int u, int tp) {
        top[u]=tp;
        w[u]=++num;
        if(son[u])dfs2(son[u],tp);
        for(int i = head[u];i!=-1;i=v[i].next){
            int to=v[i].to;
            if(to==fa[u]||to==son[u])continue;
            dfs2(to,to);
        }
    }
    struct Node
    {
        int x,y,val;
    }e[maxn];
    
    int sum[maxn<<2];
    void pushup(int rt)
    {
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    void build(int l,int r,int rt)
    {
        if(l==r){
            sum[rt]=a[l];
            return ;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        pushup(rt);
    }
    void update(int x,int val,int l,int r,int rt)
    {
        if(l==r){
            sum[rt]=val;
            return ;
        }
        int mid=(l+r)>>1;
        if(x<=mid)update(x,val,l,mid,rt<<1);
        else update(x,val,mid+1,r,rt<<1|1);
        pushup(rt);
    }
    int query(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R){
            return sum[rt];
        }
        int mid=(l+r)>>1;
        int ans=0;
        if(L<=mid)ans+=query(L,R,l,mid,rt<<1);
        if(mid<R)ans+=query(L,R,mid+1,r,rt<<1|1);
        return ans;
    }
    int modify(int x,int y)
    {
        int res=0;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            res+=query(w[top[x]],w[x],1,num,1);
            x=fa[top[x]];
        }
        if(x==y)return res;
        if(dep[x]>dep[y])swap(x,y);
        res+=query(w[son[x]],w[y],1,num,1);
        return res;
    }
    int main()
    {
        while(~scanf("%d%d%d",&n,&m,&s)){
            init();
            for(int i=1;i<n;i++){
                scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].val);
                addedge(e[i].x,e[i].y);
                addedge(e[i].y,e[i].x);
            }
            dfs1(1,0,1);
            dfs2(1,1);
            for(int i=1;i<n;i++){
                if(dep[e[i].x]<dep[e[i].y])
                    swap(e[i].x,e[i].y);
                a[w[e[i].x]]=e[i].val;
            }
            build(1,num,1);
            for(int i=0;i<m;i++){
                int op,x,y;
                scanf("%d",&op);
                if(op==0){
                    scanf("%d",&x);
                    printf("%d
    ",modify(s,x));
                    s=x;
                }
                else{
                    scanf("%d%d",&x,&y);
                    update(w[e[x].x],y,1,num,1);
                }
            }
        }
        return 0;
    }
    /*
    3 3 1
    1 2 1
    2 3 2
    0 2
    1 2 3
    0 3
    
    3 3 1
    1 2 1
    2 3 2
    0 2
    */
  • 相关阅读:
    基于shell脚本比较数字加减乘除 要bc计算器
    基于shell脚本比较数字大小
    备份WordPress
    在CentOS 7 安装没有mysql
    SQL中判断字符串中包含字符的方法
    ASP.NET生成的HTML代码
    win7禁用休眠,献给c盘空间不足的朋友.
    SQLServer2005和2008的分页技术比较[转]
    浏览器兼容性系列--浅谈window.attachEvent
    在ASP.NET 的服务器端控件中有三种关于 ID 的属性
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9745751.html
Copyright © 2020-2023  润新知