BZOJ 1036 [ZJOI2008]树的统计Count 树链剖分裸题

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 17022 Solved: 6939


Description

  一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身


Input

  输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。


Output

  对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。


Sample Input

4

1 2

2 3

4 1

4 2 1 3

12

QMAX 3 4

QMAX 3 3

QMAX 3 2

QMAX 2 3

QSUM 3 4

QSUM 2 1

CHANGE 1 5

QMAX 3 4

CHANGE 3 6

QMAX 3 4

QMAX 2 4

QSUM 3 4


Sample Output

4

1

2

2

10

6

5

6

5

16


题解:

1A过,树链剖分裸题,您的确会发现为什么这篇博客代码有空格,因为我是改的上海某dalao的代码,然后改了四个错之后1A了借了代码


#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;

const int MAXN = 33333;

int Sum[MAXN*4], Max[MAXN*4];

struct Edge {
    int v, x;
} E[MAXN*2];

int l[MAXN];
int fa[MAXN];
int dep[MAXN];
int top[MAXN];
int p[MAXN];
int fp[MAXN];
int size[MAXN];
int son[MAXN];
int val[MAXN];

int e = 0;
int tid = 0;

void insert(int u, int v) {
    E[e].v = v, E[e].x = l[u], l[u] = e++;
    E[e].v = u, E[e].x = l[v], l[v] = e++;
}

void dfs(int u, int f, int d) {
    dep[u] = d;
    fa[u] = f;
    size[u] = 1;
    for (int p = l[u]; p != -1; p = E[p].x) {
        int v = E[p].v;
        if (v == f) continue;
        dfs(v, u, d+1);
        size[u] += size[v];
        if ( son[u] == -1 || size[v] > size[son[u]]) {
            son[u] = v;
        }
    }
}

void findtop(int u, int tp) {
    p[u] = ++tid;
    fp[p[u]] = u;
    top[u] = tp;
    if (son[u] == -1) return;
    findtop(son[u], tp);
    for (int p = l[u]; p != -1; p = E[p].x) {
        int v = E[p].v;
        if (v != son[u] && v != fa[u]) {
            findtop(v, v);
        }
    }
}

int n = 0;

#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1

void pushUp(int rt) {
    Sum[rt] = Sum[rt << 1] + Sum[rt << 1 | 1];
    Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
}

void build (int l, int r, int rt) {
    if (l == r) {
        Sum[rt] = Max[rt] = val[fp[l]];
        return;
    }
    int m = (l + r) >> 1;
    build (lson);
    build (rson);
    pushUp(rt);
}

void update(int p, int v, int l, int r, int rt) {
    if (l == r) {
        Sum[rt] = Max[rt] = v;
        return;
    }
    int m = (l + r) >> 1;
    if (p <= m) update(p, v, lson);
    else update(p, v, rson);
    pushUp(rt);
}

int querySum(int L, int R, int l, int r, int rt) {
    if (L <= l && r <= R) {
        return Sum[rt];
    }
    int m = (l + r) >> 1;
    int ret = 0;
    if (L <= m) ret += querySum(L, R, lson);
    if (R > m) ret += querySum(L, R, rson);
    return ret;
}

int queryMax(int L, int R, int l, int r, int rt) {
    if (L <= l && r <= R) {
        return Max[rt];
    }
    int m = (l + r) >> 1;
    int ret = -2147483647;
    if (L <= m) ret = max(ret, queryMax(L, R, lson));
    if (R > m) ret = max(ret, queryMax(L, R, rson));
    return ret;
}

pair<int, int> myQuery(int u, int v) {
    int ansMax = -233333333;
    int ansSum = 0;
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        ansSum += querySum(p[top[u]], p[u], 1, n, 1);
        ansMax = max(ansMax, queryMax(p[top[u]], p[u], 1, n, 1));
        u = fa[top[u]];
    }
    if (dep[u] > dep[v]) swap(u, v);
    ansSum += querySum(p[u], p[v], 1, n, 1);
    ansMax = max(ansMax, queryMax(p[u], p[v], 1, n, 1));
    return make_pair(ansSum, ansMax);
}

int main () {
    memset(l, -1, sizeof(l));
    memset(son, -1, sizeof(son));
    scanf("%d", &n);
    for (int i = 1; i < n; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        insert(u, v);
    }
    dfs(1, 0, 0);
    findtop(1, 1);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &val[i]);
    }
    build(1, n, 1);
    int q = 0;
    scanf("%d", &q);
    char ch[11];
    for (int i = 1; i <= q; i++) {
        scanf("%s", ch);
        int u, v;
        scanf("%d%d", &u, &v);
        if (ch[1] == 'M') {
            pair<int, int> a = myQuery(u, v);
            printf("%d\n", a.second);
        } else if (ch[1] == 'H') {
            update(p[u], v, 1, n, 1);
        } else if (ch[1] == 'S') {
            pair<int, int> a = myQuery(u, v);
            printf("%d\n", a.first);
        }
    }
    return 0;
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的高校科研信息管理系统实现了操作日志管理、字典管理、反馈管理、公告管理、科研成果管理、科研项目管理、通知管理、学术活动管理、学院部门管理、科研人员管理、管理员管理等功能。系统用到了关系型数据库中王者MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让高校科研信息管理系统更能从理念走到现实,确确实实的让人们提升信息处理效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值