洛谷 2590 树的统计

这个题主要是一些线段树和树剖的基本操作,这里不再赘述(反正大家都会)

不过还是提几个小细节:

1. 注意点的树上编号和新编号的转换和使用(特别是单点修改时)。

2. 点权有负数,maxans的最小值要赋到-30001。

AC代码:

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

using namespace std;

const int MAXN = 500030;

int n, cnt, nid;
int f[MAXN];
int top[MAXN];
int son[MAXN];
int lid[MAXN];
int dep[MAXN];
int siz[MAXN];
int val[MAXN];
int nva[MAXN];
int faz[MAXN];

string s;

int read()
{
    int x = 0;
    int k = 1;
    char c = getchar();
    
    while (!isdigit(c))
        if (c == '-') k = -1, c = getchar();
        else c = getchar();
    while (isdigit(c))
        x = (x << 3) + (x << 1) + (c ^ 48),
        c = getchar();
    
    return k * x;
}

struct edge
{
    int w;
    int u;
    int v;
    int next;
}e[MAXN<<1];

void addedge(int x, int y)
{
    ++cnt;
    e[cnt].u = x;
    e[cnt].v = y;
    e[cnt].next = f[x];
    f[x] = cnt;
}

void dfs1(int u, int father, int depth)
{
    dep[u] = depth;
    faz[u] = father;
    siz[u] = 1;
    
    for (int i = f[u]; i != -1; i = e[i].next)
    {
        int to = e[i].v;
        if (to == father) continue;
        dfs1(to, u, depth + 1);
        siz[u] += siz[to];
        if (siz[to] > siz[son[u]] || son[u] == -1) son[u] = to;
    } 
} 

void dfs2(int u, int h)
{
    ++nid;
    lid[u] = nid;
    nva[nid] = val[u];
    top[u] = h;
    
    if (son[u] == -1) return;
    
    dfs2(son[u], h);
    
    for (int i = f[u]; i != -1; i = e[i].next)
    {
        int to = e[i].v;
        if (!lid[to]) dfs2(to, to);
    } 
}

// Segmenttree

#define ls u << 1
#define rs u << 1 | 1

struct segtree
{
    int l;
    int r;
    int w;
    int b;
    int siz;
}t[MAXN << 2];

void update(int u)
{
    t[u].w = t[ls].w + t[rs].w;
    t[u].b = max(t[ls].b, t[rs].b);
}

void build(int u, int l, int r)
{
    t[u].l = l;
    t[u].r = r;
    t[u].siz = r - l + 1;
    if (l == r) 
    {
        t[u].w = nva[l];
        t[u].b = nva[l];
        return; 
    }
    int mid = (l + r) >> 1;
    build(ls, l, mid);
    build(rs, mid + 1, r);
    update(u);
}

void change(int u, int ll, int c)
{
    if (t[u].l == t[u].r && t[u].l == ll)
    {
        t[u].w = c; 
        t[u].b = c;
        return;
    }
    int mid = (t[u].l + t[u].r) >> 1;
    if (ll <= mid) change(ls, ll, c);
    if (ll > mid) change(rs, ll, c);
    update(u);
}

int max_(int u, int l, int r)
{
    if (t[u].l >= l && t[u].r <= r)
        return t[u].b;
    int mid = (t[u].l + t[u].r) >> 1;
    int ans = -1000000000;
    if (l <= mid) ans = max(ans, max_(ls, l, r));
    if (r > mid) ans = max(ans, max_(rs, l, r));
    return ans;
}

int sum_(int u, int l, int r)
{
    if (t[u].l >= l && t[u].r <= r)
        return t[u].w;
    int mid = (t[u].l + t[u].r) >> 1;
    int ans = 0;
    if (l <= mid) ans += sum_(ls, l, r);
    if (r > mid) ans += sum_(rs, l, r);
    return ans; 
}

//sparate

int tsum_(int x, int y)
{
    int ans = 0;
    while (top[x] != top[y])
    {
        if (dep[top[x]] < dep[top[y]]) swap(x, y);
        ans += sum_(1, lid[top[x]], lid[x]);
        x = faz[top[x]];
    } 
    if (dep[x] > dep[y]) swap(x, y);
    ans += sum_(1, lid[x], lid[y]);
    return ans;
} 

int tmax_(int x, int y)
{
    int ans = -10000000;
    while (top[x] != top[y])
    {
        if (dep[top[x]] < dep[top[y]]) swap(x, y);
        ans = max(ans, max_(1, lid[top[x]], lid[x]));
        x = faz[top[x]];
    } 
    if (dep[x] > dep[y]) swap(x, y);
    ans = max(ans, max_(1, lid[x], lid[y]));
    return ans;
}

//main

int main()
{
    memset(son, -1, sizeof(son));
    memset(f, -1, sizeof(f));
    n = read();
    for (int i = 1; i < n; ++i) 
    {
        int x, y;
        x = read();
        y = read();
        addedge(x, y);
        addedge(y, x);
    }
    for (int i = 1; i <= n; ++i) val[i] = read();
    
    dfs1(1, 0, 1);
    dfs2(1, 1);
    build(1, 1, n);
    
    int q = read();
    while (q--)
    {
        cin >> s;
        int x = read();
        int y = read();
        if (s[1] == 'H')
            change(1, lid[x], y); 
        else if (s[1] == 'S')
            printf("%d\n", tsum_(x, y));
        else if (s[1] == 'M')
            printf("%d\n", tmax_(x, y));
    }
    
}

猜你喜欢

转载自www.cnblogs.com/yanyiming10243247/p/9704753.html
今日推荐