ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

BZOJ: 3531: [Sdoi2014]旅行 (树链剖分+动态线段树)

2019-08-10 20:42:40  阅读:167  来源: 互联网

标签:return 剖分 max ll mid 树链 3531 query sum


题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3531

解题心得:

  • 关于树剖的部分很容易想到,树上的简单路径维护值的问题肯定是要树链剖分了,但是线段树怎么维护就很讲究了,因为有不同的阵营,如果维护每个阵营就需要建立n颗线段树,如果静态建立线段树肯定会MLE,这里就只需要动态建立线段树就行了。
  • 在树链剖分的时候,在同一条重链上重链的哪一个端点设定的标号更大一定要搞清楚,不然线段树对应的区间就要写反,写BUG了还过了一个88MB的数据,找了半天没发现,结果还是对拍来得快。之前想到88MB的数据都过了,就没去想对拍但是眼睛都看瞎了都没发现BUG。


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 2e6+1000;

struct Node {
    ll belong, va, num, fa, gr_fa, deep, size;
}p[maxn];

struct Node2 {
    ll ls, rs, sum, max;
}node[maxn];

vector <ll> ve[maxn];

ll n, m, rt[maxn], Index, tot;

void init() {
    scanf("%lld%lld",&n, &m);
    for(ll i=1;i<=n;i++) {
        ll a, b; scanf("%lld%lld", &a, &b);
        p[i].va = a;
        p[i].belong = b;
    }

    for(ll i=1;i<n;i++) {
        ll a, b; scanf("%lld%lld",&a, &b);
        ve[a].push_back(b);
        ve[b].push_back(a);
    }
}

ll get_deep_size(ll pre, ll now, ll dep) {
    p[now].fa = pre;
    p[now].deep = dep;
    p[now].size = 1;

    for(ll i=0;i<ve[now].size();i++) {
        ll v = ve[now][i];
        if(v == pre) continue;
        p[now].size += get_deep_size(now, v, dep+1);
    }

    return p[now].size;
}

void dfs(ll pre, ll now, ll w) {
    if(w == 0) p[now].gr_fa = now;
    else p[now].gr_fa = p[pre].gr_fa;

    p[now].num = ++Index;

    ll Max = 0, pos = -1;
    for(ll i=0;i<ve[now].size();i++) {
        ll v = ve[now][i];
        if(v == pre) continue;
        if(p[v].size > Max) {
            Max = p[v].size;
            pos = v;
        }
    }

    if(pos == -1) return;

    dfs(now, pos, 1);

    for(ll i=0;i<ve[now].size();i++) {
        ll v = ve[now][i];
        if(v == pre || v == pos) continue;
        dfs(now, v, 0);
    }
}

void update(ll root) {
    node[root].sum = node[node[root].ls].sum + node[node[root].rs].sum;
    node[root].max = max(node[node[root].ls].max, node[node[root].rs].max);
}

void insert(ll root, ll l, ll r, ll pos, ll va) {
    if(l == r) {
        node[root].sum = va;
        node[root].max = va;
        return ;
    }

    ll mid = l + r >> 1;
    if(pos <= mid) {
        if(node[root].ls == 0) node[root].ls = ++tot;
        insert(node[root].ls, l, mid, pos, va);
    } else {
        if(node[root].rs == 0) node[root].rs = ++tot;
        insert(node[root].rs, mid+1, r, pos, va);
    }
    update(root);
}

void build_tree() {
    for(ll i=1;i<=n;i++) {
        ll pos = p[i].num;
        if(rt[p[i].belong] == 0) {
            rt[p[i].belong] = ++tot;
        }
        insert(rt[p[i].belong], 1, Index, pos, p[i].va);
    }
}

ll query_sum(ll root, ll l, ll r, ll ql, ll qr) {
    if(root == 0) return 0;
    if(l == ql && r == qr) return node[root].sum;

    ll mid = l + r >>1;
    if(qr <= mid) return query_sum(node[root].ls, l, mid, ql, qr);
    else if(ql > mid) return query_sum(node[root].rs, mid+1, r, ql, qr);
    else {
        return query_sum(node[root].ls, l, mid, ql, mid) +
               query_sum(node[root].rs, mid+1, r, mid+1, qr);
    }
}

ll query_max(ll root, ll l, ll r, ll ql, ll qr) {
    if(root == 0) return 0;
    if(l == ql && r == qr) return node[root].max;

    ll mid = l + r >> 1;
    if(qr <= mid) return query_max(node[root].ls, l, mid, ql, qr);
    else if(ql > mid) return query_max(node[root].rs, mid+1, r, ql, qr);
    else return max(query_max(node[root].ls, l, mid, ql, mid),
                    query_max(node[root].rs, mid+1, r, mid+1, qr));
}

ll query(ll x, ll y, ll belong, ll w) {
    ll sum = 0, Max = 0;
    while(p[x].gr_fa != p[y].gr_fa) {
        if(p[p[x].gr_fa].deep < p[p[y].gr_fa].deep) swap(x, y);

        ll r = p[x].num;
        ll l = p[p[x].gr_fa].num;

        if(w == 0) {
            sum += query_sum(rt[belong], 1, Index, l, r);
        } else {
            Max = max(Max, query_max(rt[belong], 1, Index, l, r));
        }

        x = p[p[x].gr_fa].fa;
    }

    if(p[x].num > p[y].num) swap(x, y);
    if(w == 0) sum += query_sum(rt[belong], 1, Index, p[x].num, p[y].num);
    else Max = max(Max, query_max(rt[belong], 1, Index, p[x].num, p[y].num));

    if(w == 0) return sum;
    else return Max;
}


vector <int> path;
bool dfs2(int pre, int now, int aim) {
    if(now == aim) {
        path.push_back(now);
        return true;
    }

    for(int i=0;i<ve[now].size();i++) {
        int v = ve[now][i];
        if(v == pre) continue;
        if(dfs2(now, v, aim)) {
            path.push_back(now);
            return true;
        }
    }
    return false;
}

int main() {
//    freopen("1.in.txt", "r", stdin);
    init();
    get_deep_size(1, 1, 1);
    dfs(1, 1, 0);
    build_tree();

    while(m--) {
        char s[5];
        scanf("%s", s);
        if(strcmp(s, "CC") == 0) {
            ll a, b; scanf("%lld%lld", &a, &b);
            insert(rt[p[a].belong], 1, Index, p[a].num, 0);
            p[a].belong = b;
            if(rt[p[a].belong] == 0) rt[p[a].belong] = ++tot;
            insert(rt[p[a].belong], 1, Index, p[a].num, p[a].va);
        } else if(strcmp(s, "CW") == 0) {
            ll a, b; scanf("%lld%lld",&a, &b);
            p[a].va = b;
            insert(rt[p[a].belong], 1, Index, p[a].num, b);
        } else if(strcmp(s, "QS") == 0) {
            ll a, b;
            scanf("%lld%lld", &a, &b);
            printf("%lld\n", query(a, b, p[b].belong, 0));
        } else {
            ll a, b; scanf("%lld%lld", &a, &b);
            printf("%lld\n", query(a, b, p[b].belong, 1));
        }
    }
    return 0;
}

标签:return,剖分,max,ll,mid,树链,3531,query,sum
来源: https://blog.csdn.net/yopilipala/article/details/99108496

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有