zoukankan      html  css  js  c++  java
  • codedecision P1113 同颜色询问 题解 线段树动态开点

    题目描述:https://www.cnblogs.com/problems/p/11789930.html
    题目链接:http://codedecision.com/problem/1113
    这道题目涉及的一个知识点是它最多有 (n = 10^5) 种颜色,而我们需要每种颜色动态去建树。
    那么,如果按照传统方法去建一棵线段树,每一棵树都需要 (n imes 4) 个节点,那么总的节点数就会达到 (n^2 imes 4 = 4 imes 10^{10}) 数量级,是不能承受的。
    那么,可以考虑动态建树,即一开始我创建 (n) 棵线段树,但是只创建 (n) 个根节点, (root[i]) 表示颜色为 (i) 的线段树的根节点,我们知道只有更新操作才会涉及对节点的更新。
    而这里都是单点更新,这就意味着每次更新只会最多扩展 (lceil log_2n ceil) 个节点,那么就算所有的操作都是更新,总共也只会扩展 (q imes log_2n) 个节点,而 (q le 10^5) 所以总量是可以承受的。
    然后就按照这种思路来给线段树动态开点,即可解决这个问题(然而我一开始用数组处理的时候有bug但是一直没有找到bug所在 我实在是太水了囧 ,所以就用指针的形式来解决了这个问题,所以下面是指针形式动态开点实现的代码)。
    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 100000;
    struct Tnode {
        int l, r, sumw, maxw;
        Tnode *lson, *rson;
        Tnode(int _l, int _r, int _sumw, int _maxw) { l = _l; r = _r; sumw = _sumw; maxw = _maxw; lson = rson = NULL; }
    } *root[maxn+1];
    int n, q, w[maxn+1], c[maxn+1];
    void push_up(Tnode *rt) {
        rt->sumw = rt->maxw = 0;
        if (rt->lson != NULL) {
            rt->sumw += rt->lson->sumw;
            rt->maxw = max(rt->maxw, rt->lson->maxw);
        }
        if (rt->rson != NULL) {
            rt->sumw += rt->rson->sumw;
            rt->maxw = max(rt->maxw, rt->rson->maxw);
        }
    }
    void update(int p, int v, Tnode *rt) {
        int l = rt->l, r = rt->r, mid = (rt->l + rt->r) / 2;
        if (l == r) {
            rt->sumw = rt->maxw = v;
            return;
        }
        if (p <= mid) {
            if (rt->lson == NULL) rt->lson = new Tnode(l, mid, 0, 0);
            update(p, v, rt->lson);
        }
        else {
            if (rt->rson == NULL) rt->rson = new Tnode(mid+1, r, 0, 0);
            update(p, v, rt->rson);
        }
        push_up(rt);
    }
    int query_sum(int L, int R, Tnode *rt) {
        int l = rt->l, r = rt->r, mid = (rt->l + rt->r) / 2;
        if (L <= l && r <= R) return rt->sumw;
        int tmp = 0;
        if (L <= mid && rt->lson != NULL) tmp += query_sum(L, R, rt->lson);
        if (R > mid && rt->rson != NULL) tmp += query_sum(L, R, rt->rson);
        return tmp;
    }
    int query_max(int L, int R, Tnode *rt) {
        int l = rt->l, r = rt->r, mid = (rt->l + rt->r) / 2;
        if (L <= l && r <= R) return rt->maxw;
        int tmp = 0;
        if (L <= mid && rt->lson != NULL) tmp = max(tmp, query_max(L, R, rt->lson));
        if (R > mid && rt->rson != NULL) tmp = max(tmp, query_max(L, R, rt->rson));
        return tmp;
    }
    void init() {
        for (int i = 1; i <= maxn; i ++) root[i] = new Tnode(1, n, 0, 0);
    }
    string op;
    int x, y;
    int main() {
        cin >> n >> q;
        init();
        for (int i = 1; i <= n; i ++) {
            cin >> w[i] >> c[i];
            update(i, w[i], root[c[i]]);
        }
        while (q --) {
            cin >> op >> x >> y;
            if (op == "CC") {
                update(x, 0, root[c[x]]);
                c[x] = y;
                update(x, w[x], root[c[x]]);
            }
            else if (op == "CW") {
                w[x] = y;
                update(x, y, root[c[x]]);
            }
            else if (op == "QS") {
                cout << query_sum(x, y, root[c[x]]) << endl;
            }
            else {  // QM
                cout << query_max(x, y, root[c[x]]) << endl;
            }
        }
    
        return 0;
    }
    
  • 相关阅读:
    jwt的简单使用
    使用golang对海康sdk进行业务开发
    产品项目开发流程
    Unity在场景切换之间清理下内存
    Unity3d中第三人称摄像机跟随的实现
    unity3d中利用网格去绘制血条
    java内存泄露原因简单总结
    线程安全的多参构建器实现
    java单例模式,多线程下实现
    forward和redirect的简单区别
  • 原文地址:https://www.cnblogs.com/codedecision/p/11791200.html
Copyright © 2011-2022 走看看