zoukankan      html  css  js  c++  java
  • 洛谷 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
    ", tsum_(x, y));
            else if (s[1] == 'M')
                printf("%d
    ", tmax_(x, y));
        }
        
    }
  • 相关阅读:
    django-restframework频率功能、过滤功能等相关内容-87
    django-restframework认证功能等相关内容-86
    视图基类、扩展类、子类及试图集等相关内容-85
    vue框架前后端分离项目之课程接口、页面、前台等相关内容-127
    vue框架前后端分离项目之课程页面前端、课程表分析、编写及数据录入等相关内容-126
    celery的基础使用等相关内容-125
    数据库时间戳排序协议
    单节点部署OpenStack(Queens版本、DevStack)
    变量命名规范及str类型
    程序员职业生涯规划
  • 原文地址:https://www.cnblogs.com/yanyiming10243247/p/9704753.html
Copyright © 2011-2022 走看看