题目描述:https://www.cnblogs.com/problems/p/11789930.html

题目链接:http://codedecision.com/problem/1113

这道题目涉及的一个知识点是它最多有 \(n = 10^5\) 种颜色,而我们需要每种颜色动态去建树。

那么,如果按照传统方法去建一棵线段树,每一棵树都需要 \(n \times 4\) 个节点,那么总的节点数就会达到 \(n^2 \times 4 = 4 \times 10^{10}\) 数量级,是不能承受的。

那么,可以考虑动态建树,即一开始我创建 \(n\) 棵线段树,但是只创建 \(n\) 个根节点, \(root[i]\) 表示颜色为 \(i\) 的线段树的根节点,我们知道只有更新操作才会涉及对节点的更新。

而这里都是单点更新,这就意味着每次更新只会最多扩展 \(\lceil \log_2n \rceil\) 个节点,那么就算所有的操作都是更新,总共也只会扩展 \(q \times \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;
}

codedecision P1113 同颜色询问 题解 线段树动态开点的更多相关文章

  1. P3939 数颜色 线段树动态开点

    P3939 数颜色 线段树动态开点 luogu P3939 水.直接对每种颜色开个权值线段树即可,注意动态开点. #include <cstdio> #include <algori ...

  2. 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点

    题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...

  3. HDU - 6183 暴力,线段树动态开点,cdq分治

    B - Color itHDU - 6183 题目大意:有三种操作,0是清空所有点,1是给点(x,y)涂上颜色c,2是查询满足1<=a<=x,y1<=b<=y2的(a,b)点一 ...

  4. hdu6183 Color it 线段树动态开点+查询减枝

    题目传送门 题目大意: 有多次操作.操作0是清空二维平面的点,操作1是往二维平面(x,y)上放一个颜色为c的点,操作2是查询一个贴着y轴的矩形内有几种颜色的点,操作3退出程序. 思路: 由于查询的矩形 ...

  5. BZOJ_4636_蒟蒻的数列_线段树+动态开点

    BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...

  6. BZOJ4999:This Problem Is Too Simple!(DFS序&树上差分&线段树动态开点:区间修改单点查询)

    Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x&l ...

  7. codedecision P1112 区间连续段 题解 线段树

    题目描述:https://www.cnblogs.com/problems/p/P1112.html 题目链接:http://codedecision.com/problem/1112 线段树区间操作 ...

  8. 2019.03.09 bzoj4999: This Problem Is Too Simple!(树链剖分+线段树动态开点)

    传送门 题意:给一颗树,每个节点有个初始值,要求支持将i节点的值改为x或询问i节点到j节点的路径上有多少个值为x的节点. 思路: 考虑对每种颜色动态开点,然后用树剖+线段树维护就完了. 代码: #in ...

  9. hdu 6183 Color it (线段树 动态开点)

    Do you like painting? Little D doesn't like painting, especially messy color paintings. Now Little B ...

随机推荐

  1. 洛谷P2258 子矩阵[2017年5月计划 清北学堂51精英班Day1]

    题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第2.4行和第2.4.5列交叉位置的元素 ...

  2. 使用Cmder 安装 Composer 出现 "attempt to call a nil value"

    原因: 不是这个原因,也不是那个原因,而是采用了中文路径, 把comder 整个搬到其他目录就行了

  3. 将jacoco集成到测试工具平台

    最近在做接口测试,想通过代码覆盖率来判断一下接口用例是否缺失,但是每次通过命令来生成覆盖率报告,感觉太麻烦,所以就想着把jacoco集成到测试工具平台中,只需要点几个按钮,就能查看到覆盖率报告. 测试 ...

  4. node的源码安装

    Node.js 安装配置 本章节我们将向大家介绍在 Windows 和 Linux 上安装 Node.js 的方法. 本安装教程以 Node.js v4.4.3 LTS(长期支持版本)版本为例. No ...

  5. PHP的注释规范

    <?php //注释规范 /** *函数的功能 *@param 参数类型 参数名1 参数解析 *@param 参数类型 参数名2 参数解析 *@return 返回值类型 返回值解析 *@auth ...

  6. ANN中乘积量化与多维倒排小结

    目前特征向量的比对加速优化能极大缩短比对耗时,改善用户体验. 优化的途径主要有两种,一是使用指令集(SSE,AVX)加速运算.二是使用ANN替代暴力搜索. 乘积量化和倒排索引组合是ANN中效果较好且实 ...

  7. C++的替代运算标记符

    标记符and, and_eq, bitand, bitor, compl, not, not_eq, or, or_eq, xor, xor_eq, <%, %>, <: 和 :&g ...

  8. SPSS详细操作:生存资料的Cox回归分析

    SPSS详细操作:生存资料的Cox回归分析 一.问题与数据 某研究者拟观察某新药的抗肿瘤效果,将70名肺癌患者随机分为两组,分别采用该新药和常规药物进行治疗,观察两组肺癌患者的生存情况,共随访2年.研 ...

  9. linux中各目录及详细介绍

    一.Linux文件系统的层次结构 在Linux或UNIX操作系统中,所有的文件和目录都被组织成一个以根节点开始的倒置的树状结构,如图: 二.目录 1.目录的定义 目录相当于Windows中的文件夹,目 ...

  10. js的下拉刷新和上拉加载,基于iScroll v4.2.5

    html部分 <div id="wrapper" style="height: 100%"> <div id="scroller&q ...