题目描述: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. Leetcode61. Rotate List旋转链表

    给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: 1->2->3->4->5->NULL, k = 2 输出: 4-& ...

  2. Data Visualisation Cheet Sheet

    Univariate plotting with pandas import pandas as pd reviews = pd.read_csv() reviews.head() //bar rev ...

  3. DesktopLayer.exe专杀

    这两天发现电脑卡慢. 同事电脑发现病毒,而后装上杀软后(一直在裸奔~~~),发现自己电脑也存在. DesktopLayer.exe 会有以下几个行为: 第一,会在C:\Program Files (x ...

  4. ecshop二次开发之后台秒杀

    1.进入admin->includes->inc_menu.PHP中此文件为定义左侧功能模块超链接 2.添加include/inc_menu.php秒杀管理超链接找链接 $modules[ ...

  5. 移动端fixed定位在底部,出现键盘后消失

    jq var h=$(window).height(); $(window).resize(function() { if($(window).height()<h){ $('.nav').hi ...

  6. SAS-一些有用的语句

    SAS-一些有用的语句 今天本想继续介绍 summary过程的,但是发现别人整理的比我更好,于是周末再更,好好整理一下描述性统计分析及评分卡建模,今天给大家介绍一些sas有用的语句吧. 1.如果在同一 ...

  7. mysqldump命令之数据库迁移

    格式说明如下: mysqldump -h源主机IP -u源主机用户 -p源主机用户密码 数据库名 | mysql -h目标主机IP -u目标主机用户 -p目标用户密码 数据库名 

  8. Directx11教程(35) 纹理映射(5)

    原文:Directx11教程(35) 纹理映射(5)     到现在为止,我们的TextureClass初始化函数非常简单,说白了就是一行代码: result = D3DX11CreateShader ...

  9. Directx11教程(32) 纹理映射(2)

    原文:Directx11教程(32) 纹理映射(2)     在写代码之前,我们先制作一个dds文件.从网上找到了一张照片,处理成为512*512,保存为jpg格式.     启动微软的directx ...

  10. JDK源码解析string之二

    (28) public boolean startsWith(String prefix, int toffset) { char ta[] = value; int to = toffset; ch ...