树链剖分 poj 2763

n个点q个查询开始位置s

n-1条边 a b  c   a b之间有一条边  权值为c

q个查询   0  a  输出现在的位置到 a 所需时间

      1  a  b  更新第a条边的权为b

#include<stdio.h>
#include<string.h>
#include<algorithm>

using namespace std;

#define MAXN  100010
struct edge
{
    int from,to,w,next;
}x[MAXN<<1],s1[MAXN];

int head[MAXN],siz[MAXN],father[MAXN],dep[MAXN],top[MAXN],intree[MAXN],outtree[MAXN],son[MAXN],val[MAXN];
int cnt,tim,n;

void add(int u,int v,int w)
{
    x[cnt].from=u;
    x[cnt].to=v;
    x[cnt].w=w;
    x[cnt].next=head[u];
    head[u]=cnt++;
}

void dfs1(int u,int fa)
{
    siz[u]=1;
    father[u]=fa;
    dep[u]=dep[fa]+1;
    for(int i=head[u];i!=-1;i=x[i].next)
    {
        int v=x[i].to;
        if(v==fa)
            continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]])
            son[u]=v;
    }
}

void dfs2(int u,int tp)
{
    top[u]=tp;
    intree[u]=++tim;
    outtree[tim]=u;
    if(son[u]!=0)
        dfs2(son[u],tp);
    for(int i=head[u];i!=-1;i=x[i].next)
    {
        int v=x[i].to;
        if(v==son[u]||v==father[u])
            continue;
        dfs2(v,v);
    }

}
struct node
{
    int l,r,w;
}z[MAXN<<3];

void Build(int l,int r,int a)
{
    z[a].l=l;
    z[a].r=r;
    if(l==r)
    {
        z[a].w=val[l];
        return ;
    }
    int mid=(l+r)>>1;
    Build(l,mid,a<<1);
    Build(mid+1,r,a<<1|1);
    z[a].w=z[a<<1].w+z[a<<1|1].w;
}
void update(int l,int r,int a1,int w,int a)//单点更新
{
    if(l==r)
    {
        z[a].w=w;
        return ;
    }
    int mid=(l+r)>>1;
    if(a1<=mid)
        update(l,mid,a1,w,a<<1);
    else
        update(mid+1,r,a1,w,a<<1|1);
    z[a].w=z[a<<1].w+z[a<<1|1].w;
}
int ques(int l,int r,int a1,int b1,int a)//区间求和
{
    int ans=0;
    if(a1<=l&&r<=b1)
        return z[a].w;
    int mid=(l+r)>>1;
    if(a1<=mid)
        ans+=ques(l,mid,a1,b1,a<<1);
    if(b1>mid)
        ans+=ques(mid+1,r,a1,b1,a<<1|1);
    return ans;
}
int change(int x,int y)
{
    int ans=0;

    while(top[x] != top[y])
    {
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        ans+=ques(1,n,intree[top[x]],intree[x],1);
        x=father[top[x]];
    }

    if(x==y)
        return ans;
    if(dep[x] > dep[y])
        swap(x,y);

    ans+=ques(1,n,intree[x]+1,intree[y],1);//这边左边的是要加1的
    return ans;
}

int main()
{
    int q,s;
    while(scanf("%d%d%d",&n,&q,&s)!=EOF)
    {
        memset(head,-1,sizeof(head));
        memset(son,0,sizeof(son));
        cnt=1;
        tim=0;
        for(int i=1;i<n;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&s1[i].from,&s1[i].to,&s1[i].w);//存到另外一个数组里
            add(s1[i].from,s1[i].to,s1[i].w);
            add(s1[i].to,s1[i].from,s1[i].w);
        }
        dfs1(1,0);
        dfs2(1,1);
        for(int i=1;i<n;i++) //边的权放到点上 那么只要区间求和就可以了 其实里面还有问题
        {
            if(dep[s1[i].from]<dep[s1[i].to])
                swap(s1[i].from,s1[i].to);
            val[intree[s1[i].from]]=s1[i].w;
        }
        Build(1,n,1);
        while(q--)
        {
            int a;
            scanf("%d",&a);
            if(a==0)
            {
                int b;
                scanf("%d",&b);
                printf("%d\n",change(s,b));
                s=b;
            }
            else
            {
                int b,c;
                scanf("%d%d",&b,&c);
                update(1,n,intree[s1[b].from],c,1);
            }
        }
    }

    return 0;
}
时间: 2024-12-21 23:21:12

树链剖分 poj 2763的相关文章

树链剖分 [POJ 3237] Tree

Tree Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instruc

poj 2763 Housewife Wind(树链剖分+单点查询+区间修改)

题目链接:http://poj.org/problem?id=2763 题意:给一个数,边之间有权值,然后两种操作,第一种:求任意两点的权值和,第二,修改树上两点的权值. 题解:简单的树链剖分. #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int M = 1e5 + 10; struct Edge { int v , next; }edge[M &

POJ 2763 Housewife Wind (树链剖分)

题目地址:POJ 2763 还是树链剖分模板题...不多说.. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h>

poj 2763 树链剖分(单点更新,区间求值)

http://poj.org/problem?id=2763 Description After their royal wedding, Jiajia and Wind hid away in XX Village, to enjoy their ordinary happy life. People in XX Village lived in beautiful huts. There are some pairs of huts connected by bidirectional ro

POJ 2763 Housewife Wind(树链剖分+树状数组)

[题目链接] http://poj.org/problem?id=2763 [题目大意] 在一棵树上,给出一些边的边长,有修改边的边长的操作, 询问每次从当前点到目标点的最短距离 [题解] 树链剖分之后,相当于树状数组的单点更新和区间查询, 注意边权转点权之后链操作不覆盖deep最浅的点,这里容易出错 [代码] #include <cstdio> #include <cstring> #include <algorithm> using namespace std; c

POJ 2763 (树链剖分+边修改+边查询)

题目链接:http://poj.org/problem?id=2763 题目大意:某人初始在s点.有q次移动,每次移动沿着树上一条链,每经过一条边有一定花费,这个花费可以任意修改.问每次移动的花费. 解题思路: 树链剖分基础题.每次Q之后改变一下s. 线段树记录的是边权.方法是对于一条边(u,v),边权值加在dep比较大的那一端. 链查询(边)和 链查询(点)在轻链时略有不同. 注意本题使用vector邻接表存图是会TLE的,应该使用链式前向星.树链剖分中使用链式前向星是基本要求. #inclu

POJ 2763 Housewife Wind (树链剖分)

题目链接~~> 做题感悟:这题说多了都是泪啊 !明明是一个简单的不能再简单的树链剖分,结果因为一个符号错误找了一下午. 解题思路:   树链剖分 + 线段树插点问线. 代码: #include<iostream> #include<sstream> #include<map> #include<cmath> #include<fstream> #include<queue> #include<vector> #inc

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[m

POJ 2736 Housewife Wind(树链剖分)

POJ 2763 Housewife Wind 题目链接 就树链剖分..不过这题坑ector啊!, vector居然超时 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; #define lson(x) ((x<<1)+1) #define rson(x) ((x<<1)+2) typ