poj 2763 Housewife Wind

题目链接

分析:这道题是树链剖分的裸题,把边的信息保存在深度大的那个节点上就行了。
一开始写的邻接表,居然TLE了。后来百度发现有人说前向星跑得比较快?我不是很明白,但是改成前向星以后的确快了很多,邻接表是T,而前向星只需要2s左右。

这个代码还是邻接表,因为我不信,又修改了一下邻接表上几个我觉得会增加常数的地方,交上去还是T了- -代码里前向星的部分被注释掉了。

/*****************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <map>
#include <set>
#include <ctime>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define   offcin        ios::sync_with_stdio(false)
#define   sigma_size    26
#define   lson          l,m,v<<1
#define   rson          m+1,r,v<<1|1
#define   slch          v<<1
#define   srch          v<<1|1
#define   sgetmid       int m = (l+r)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   pb            push_back
#define   fi            first
#define   se            second

const int    INF    = 0x3f3f3f3f;
const LL     INFF   = 1e18;
const double pi     = acos(-1.0);
const double inf    = 1e18;
const double eps    = 1e-9;
const LL     mod    = 1e9+7;
const int    maxmat = 10;
const ull    BASE   = 31;

/*****************************************************/

const int maxn = 1e5 + 5;
int siz[maxn], top[maxn], son[maxn], dep[maxn], fat[maxn], tid[maxn], rid[maxn];
int seg[maxn << 2], a[maxn];
int uu[maxn], vv[maxn], ww[maxn], tim;
int N, Q, S;
std::vector<int> G[maxn];
// struct Edge {
//     int to, next;
// }edge[maxn << 1];
// int head[maxn], tot;
// void addedge(int u, int v) {
//     edge[tot] = (Edge){v, head[u]};
//     head[u] = tot ++;
// }
void dfs1(int u, int fa, int d) {
    siz[u] = 1;
    fat[u] = fa;
    dep[u] = d;
    int sz = G[u].size();
    for (int i = 0; i < sz; i ++) {
        int v = G[u][i];
        if (v == fa) continue;
        dfs1(v, u, d + 1);
        siz[u] += siz[v];
        if (son[u] == -1 || siz[v] > siz[son[u]]) son[u] = v;
    }
}
void dfs2(int u, int tp) {
    tid[u] = ++ tim;
    top[u] = tp;
    if (son[u] != -1) dfs2(son[u], tp);
    int sz = G[u].size();
    for (int i = 0; i < sz; i ++) {
        int v = G[u][i];
        if (v == son[u] || v == fat[u]) continue;
        dfs2(v, v);
    }
}
void PushUp(int v) {
    seg[v] = seg[slch] + seg[srch];
}
void build(int l, int r, int v) {
    if (l == r)
        seg[v] = a[l];
    else {
        sgetmid;
        build(lson);
        build(rson);
        PushUp(v);
    }
}
void update(int p, int val, int l, int r, int v) {
    if (l == r) {
        seg[v] = val;
    }
    else {
        sgetmid;
        if (p <= m) update(p, val, lson);
        else update(p, val, rson);
        PushUp(v);
    }
}
int query(int L, int R, int l, int r, int v) {
    if (L <= l && r <= R) return seg[v];
    int ans = 0;
    sgetmid;
    if (L <= m) ans += query(L, R, lson);
    if (R >  m) ans += query(L, R, rson);
    return ans;
}
int getv(int u, int v) {
    int tp1 = top[u], tp2 = top[v];
    int ans = 0;
    while (tp1 != tp2) {
        if (dep[tp1] < dep[tp2]) {
            swap(tp1, tp2);
            swap(u, v);
        }
        ans += query(tid[tp1], tid[u], 1, N, 1);
        u = fat[tp1];
        tp1 = top[u];
    }
    if (u == v) return ans;
    if (dep[u] > dep[v]) swap(u, v);
    ans += query(tid[son[u]], tid[v], 1, N, 1);
    return ans;
}
int main(int argc, char const *argv[]) {
    while (~scanf("%d%d%d", &N, &Q, &S)) {
        mem(son, -1);
        tim = 0;
        for (int i = 1; i < N; i ++) {
            scanf("%d%d%d", &uu[i], &vv[i], &ww[i]);
            G[uu[i]].pb(vv[i]);
            G[vv[i]].pb(uu[i]);
        }
        dfs1(1, -1, 1);
        dfs2(1, 1);
        for (int i = 1; i < N; i ++) {
            if (dep[uu[i]] > dep[vv[i]]) swap(uu[i], vv[i]);
            a[tid[vv[i]]] = ww[i];
        }
        build(1, N, 1);
        for (int i = 0; i < Q; i ++) {
            int op, x, y;
            scanf("%d", &op);
            if (op) {
                scanf("%d%d", &x, &y);
                update(tid[vv[x]], y, 1, N, 1);
            }
            else {
                scanf("%d", &x);
                int ans = getv(S, x);
                printf("%d\n", ans);
                S = x;                
            }
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/hahatianx/p/5943441.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值