LCA+树状数组 POJ 2763 Housewife Wind

题目传送门

题意:两种操作,问u到v的距离,并且u走到了v;把第i条边距离改成w

分析:根据DFS访问顺序,将树处理成链状的,那么回边处理成负权值,那么LCA加上BIT能够知道u到v的距离,BIT存储每条边的信息,这样第二种操作也能用BIT快速解决

利用RMQ的写法不知哪里写挫了,改用倍增法

/************************************************
* Author        :Running_Time
* Created Time  :2015/10/6 星期二 11:45:03
* File Name     :POJ_2763.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e5 + 10;
const int D = 20;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double EPS = 1e-8;
struct Edge {
    int v, w, id, nex;
}edge[N<<1];
struct BIT  {
    int c[N<<1], NN;
    void init(int n) {
        NN = n * 2;
        memset (c, 0, sizeof (c));
    }
    void updata(int i, int x)   {
        while (i <= NN) {
            c[i] += x;  i += i & (-i);
        }
    }
    int query(int i)    {
        int ret = 0;
        while (i)   {
            ret += c[i];    i -= i & (-i);
        }
        return ret;
    }
}bit;
int head[N];
int dep[N], rt[D][N], id[N], in[N], out[N];
int cost[N];
int e, tim;

void init(void) {
    memset (head, -1, sizeof (head));
    e = 0;
}

void add_edge(int u, int v, int w, int id)  {
    edge[e] = (Edge) {v, w, id, head[u]};
    head[u] = e++;
}

void DFS(int u, int fa, int d) {
    dep[u] = d; rt[0][u] = fa;
    for (int i=head[u]; ~i; i=edge[i].nex)  {
        Edge &e = edge[i];
        if (e.v == fa)  continue;
        in[e.id] = id[e.v] = ++tim;
        DFS (e.v, u, d + 1);
        out[e.id] = ++tim;
    }
}

int LCA(int u, int v)   {
    if (dep[u] < dep[v])    {
        swap (u, v);
    }
    for (int i=0; i<D; ++i) {
        if ((dep[u] - dep[v]) >> i & 1) {
            u = rt[i][u];
        }
    }
    if (u == v) return u;
    for (int i=D-1; i>=0; --i)  {
        if (rt[i][u] != rt[i][v])   {
            u = rt[i][u];
            v = rt[i][v];
        }
    }
    return rt[0][u];
}

int main(void)    {
    int n, q, s;
    while (scanf ("%d%d%d", &n, &q, &s) == 3)   {
        init ();
        for (int u, v, w, i=1; i<n; ++i)    {
            scanf ("%d%d%d", &u, &v, &cost[i]);
            add_edge (u, v, cost[i], i);
            add_edge (v, u, cost[i], i);
        }
        tim = 0;
        DFS (1, -1, 0);
        for (int i=1; i<D; ++i) {
            for (int j=1; j<=n; ++j)    {
                rt[i][j] = rt[i-1][j] == -1 ? -1 : rt[i-1][rt[i-1][j]];
            }
        }

        bit.init (n);
        for (int i=1; i<n; ++i) {
            bit.updata (in[i], cost[i]);        //入边序号
            bit.updata (out[i], -cost[i]);      //回边序号
        }

        int u = s;
        for (int op, i=1; i<=q; ++i)    {
            scanf ("%d", &op);
            if (op == 0)    {
                int v;  scanf ("%d", &v);               //入点序号和回点序号
                printf ("%d\n", bit.query (id[u]) + bit.query (id[v]) - bit.query (id[LCA (u, v)]) * 2);
                u = v;
            }
            else    {
                int p, w;   scanf ("%d%d", &p, &w);
                bit.updata (in[p], w - cost[p]);
                bit.updata (out[p], cost[p] - w);
                cost[p] = w;
            }
        }
    }   

    return 0;
}

  

时间: 2024-10-10 23:14:26

LCA+树状数组 POJ 2763 Housewife Wind的相关文章

POJ 2763 Housewife Wind LCA转RMQ+时间戳+线段树成段更新

题目来源:POJ 2763 Housewife Wind 题意:给你一棵树 2种操作0 x 求当前点到x的最短路 然后当前的位置为x; 1 i x 将第i条边的权值置为x 思路:树上两点u, v距离为d[u]+d[v]-2*d[LCA(u,v)] 现在d数组是变化的 对应每一条边的变化 他修改的是一个区间 用时间戳处理每个点管辖的区域 然后用线段树修改 线段树的叶子节点村的是根到每一个点的距离 求最近公共祖先没差别 只是堕落用线段树维护d数组 各种错误 4个小时 伤不起 #include <cs

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

题目链接:POJ 2763 Housewife Wind 题意:抽象出来就是 一棵已知节点之间的边权,两个操作,1·修改边权,2·询问两个节点之间的边权和. AC代码: #include <string.h> #include <stdio.h> #include <algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int

POJ 2763 Housewife Wind(DFS序+LCA+树状数组)

Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 11419   Accepted: 3140 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 beauti

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

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

HDU 6203 ping ping ping(dfs序+LCA+树状数组)

http://acm.hdu.edu.cn/showproblem.php?pid=6203 题意: n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V 无法连通.问无法通行的点最少有多少个. 思路: 贪心思维,破坏两个点的LCA是最佳的.那么怎么判断现在在(u,v)之间的路径上有没有被破坏的点呢,如果没有的话那么此时就要破坏这个lca点.一开始我们要把询问按照u和v的lca深度从大到小排序,如果某个点需要被破坏,那么它的所有子节点都可以不再需要破坏别的点

SUOI08 一收一行破 (lca+树状数组)

用一个差分树状数组维护一下每个深度的和,然后每次拿着路径端点和lca加一加减一减就行了 1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define ll long long 4 using namespace std; 5 const int maxn=200020; 6 7 inline ll rd(){ 8 ll x=0;char c=getchar();int neg=1; 9 while(c<'0'||

CF983E NN country [倍增][LCA][树状数组]

题意: $n$个城市,从$1$到$n$标号,$n$个城市构成一棵树. 有$m$条双向公交路线,对于每条路线,公交沿着两个终点站之间的最短路径行驶并会在沿途各站停车.从一个城市只能坐公交前往其他城市. 有$q$个询问:从一个城市到另一个城市要搭乘多少趟公交?不能到达输出$-1$. 对于每个询问$x,y$,求出$z=lca(x,y)$. 先从$x$和$y$出发到达$z$下方的城市$x'$和$y'$使得再坐一趟车可到$z$,记步数和为$s$.倍增,预处理$f[i][j]$表示从$i$出发坐$2^{j}

线段树/树状数组 POJ 2182 Lost Cows

题目传送门 题意:n头牛,1~n的id给它们乱序编号,已知每头牛前面有多少头牛的编号是比它小的,求原来乱序的编号 分析:从后往前考虑,最后一头牛a[i] = 0,那么它的编号为第a[i] + 1编号:为1,倒数第二头牛的编号为除去最后一头牛的编号后的第a[i-1] + 1编号:为3,其他的类推,所以可以维护之前已经选掉的编号,求第k大的数字,sum[rt] 表示该区间已经被选掉的点的个数.另外树状数组也可以做,只不过用二分优化查找第k大的位置. 收获:逆向思维,求动态第K大 代码(线段树): /

POJ 2763 Housewife Wind(树链剖分)(线段树单点修改)

Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 10378   Accepted: 2886 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 beauti