Poj2763Housewife Wind树链剖分

边查询,点更新的模板题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#include<stdlib.h>
using namespace std;
typedef long long LL;
const int maxn = 222222;

struct Node
{
    int to;int next;
}e[maxn*2];
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1

int head[maxn];
int son[maxn];
int top[maxn];
int father[maxn];
int deep[maxn];
int len;int z;
int size[maxn];
int pos[maxn];
int sum[maxn<<2];
void add(int from, int to)
{
    e[len].to = to;
    e[len].next = head[from];
    head[from] = len++;
}
int edge[maxn][10];

void init(int x)
{
    son[x] = 0; size[x] = 1;
    for (int i = head[x]; i != -1; i = e[i].next){
        int cc = e[i].to;
        if (cc == father[x]) continue;
        deep[cc] = deep[x] + 1; father[cc] = x;
        init(cc);
        size[x] += size[cc];
        if (size[son[x]] < size[cc]) son[x] = cc;
    }
}

void dfs(int x, int tp)
{
    pos[x] = ++z;top[x] = tp;
    if (son[x]) dfs(son[x], tp);
    for (int i = head[x]; i != -1; i = e[i].next){
        int cc = e[i].to;
        if (cc == father[x] || cc == son[x]) continue;
        dfs(cc, cc);
    }
}

void up(int rt)
{
    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}

void update(int key, int ans, int l, int r, int rt)
{
    if (l == r){
        sum[rt] = ans; return;
    }
    int mid = (l + r) >> 1;
    if (key <= mid) update(key, ans, lson);
    else update(key, ans, rson);
    up(rt);
}

int ask(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 += ask(L, R, lson);
    if (R > mid) ans += ask(L, R, rson);
    return ans;
}

int gao(int x, int y)
{
    int ans = 0;
    int fx = top[x]; int fy = top[y];
    while (fx != fy){
        if (deep[fx] < deep[fy]){
            swap(fx, fy); swap(x, y);
        }
        ans += ask(pos[fx], pos[x], 1, z, 1);
        x = father[fx]; fx = top[x];
    }
    if (x == y) return ans;
    if (deep[x]>deep[y]) swap(x, y);
    ans += ask(pos[x] + 1, pos[y], 1, z, 1);
    return ans;
}

int main()
{
    int n,q,s;
    int a,b,c;
    while (cin >> n >> q >> s){
        memset(sum,0,sizeof(sum));
        len = 0;z =0;
        memset(head,-1,sizeof(head));
        deep[s]=1 ;
        for (int i = 1; i < n ; i++){
            scanf("%d%d%d", &edge[i][0], &edge[i][1], &edge[i][2]);
            add(edge[i][0], edge[i][1]); add(edge[i][1], edge[i][0]);
        }
        init(1); dfs(1, 1);
        for (int i = 1; i < n ; i++){
            int a = edge[i][0]; int b = edge[i][1]; int c = edge[i][2];
            if (deep[a]>deep[b]) swap(edge[i][0], edge[i][1]);
            update(pos[edge[i][1]], c, 1, z, 1);
        }
        while (q--){
            scanf("%d", &a);
            if (a == 0){
                scanf("%d", &b);
                int t = gao(b, s);
                cout << t << endl;
                s = b;
            }
            else {
                scanf("%d%d", &b, &c);
                edge[b][2] = c;
                update(pos[edge[b][1]], c, 1, z, 1);
            }
        }
    }
    return 0;
}
时间: 2024-08-30 10:18:47

Poj2763Housewife Wind树链剖分的相关文章

poj2763--Housewife Wind(树链剖分+线段树)

Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 6898   Accepted: 1742 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 beautif

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 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 : 树链剖分维护边 O(nlogn)建树 O((logn)&#178;)修改与查询

1 /** 2 problem: http://poj.org/problem?id=2763 3 **/ 4 #include<stdio.h> 5 #include<stdlib.h> 6 #include<string.h> 7 #include<vector> 8 using namespace std; 9 10 const int MAXN = 100005; 11 12 template <typename T> 13 class

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

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(树链剖分+树状数组)

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

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