codedecision P1113 同颜色询问 题解 线段树动态开点
题目描述: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 同颜色询问 题解 线段树动态开点的更多相关文章
- P3939 数颜色 线段树动态开点
P3939 数颜色 线段树动态开点 luogu P3939 水.直接对每种颜色开个权值线段树即可,注意动态开点. #include <cstdio> #include <algori ...
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- HDU - 6183 暴力,线段树动态开点,cdq分治
B - Color itHDU - 6183 题目大意:有三种操作,0是清空所有点,1是给点(x,y)涂上颜色c,2是查询满足1<=a<=x,y1<=b<=y2的(a,b)点一 ...
- hdu6183 Color it 线段树动态开点+查询减枝
题目传送门 题目大意: 有多次操作.操作0是清空二维平面的点,操作1是往二维平面(x,y)上放一个颜色为c的点,操作2是查询一个贴着y轴的矩形内有几种颜色的点,操作3退出程序. 思路: 由于查询的矩形 ...
- BZOJ_4636_蒟蒻的数列_线段树+动态开点
BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...
- 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 ...
- codedecision P1112 区间连续段 题解 线段树
题目描述:https://www.cnblogs.com/problems/p/P1112.html 题目链接:http://codedecision.com/problem/1112 线段树区间操作 ...
- 2019.03.09 bzoj4999: This Problem Is Too Simple!(树链剖分+线段树动态开点)
传送门 题意:给一颗树,每个节点有个初始值,要求支持将i节点的值改为x或询问i节点到j节点的路径上有多少个值为x的节点. 思路: 考虑对每种颜色动态开点,然后用树剖+线段树维护就完了. 代码: #in ...
- hdu 6183 Color it (线段树 动态开点)
Do you like painting? Little D doesn't like painting, especially messy color paintings. Now Little B ...
随机推荐
- Leetcode74. Search a 2D Matrix搜索二维矩阵
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值.该矩阵具有如下特性: 每行中的整数从左到右按升序排列. 每行的第一个整数大于前一行的最后一个整数. 示例 1: 输入: matrix ...
- 阿里云数据管理DMS企业版发布年度重大更新 多项功能全面升级
随着企业规模和人员扩充,您是否遇到这些问题:企业员工还在使用数据库账号直接操作数据库?人员流动导致运维人员频繁维护数据库账号密码?所有数据库变更还在等DBA集中执行,导致研发效率日益低下. 2月27日 ...
- JAVA的一次编译,到处执行,你知道多少?
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/wangyongxia921/article/details/28117155 一.对AVA的迷茫 ...
- day38 12-Spring的Bean的属性的注入:名称空间p
xmlns="http://www.springframework.org/schema/beans"是默认的名称空间. xmlns:xsi="http://www.w3 ...
- python 运算符重复
- c++进制数转换
QString result; ]; sprintf(buffer, "0x%x", modelId); return result = buffer;
- SPSS分析技术:无序多元Logistic回归模型;美国总统大选的预测历史及预测模型
SPSS分析技术:无序多元Logistic回归模型:美国总统大选的预测历史及预测模型 在介绍有序多元Logistic回归分析的理论基础时,介绍过该模型公式有一个非常重要的假设,就是自变量对因变量多个类 ...
- Nginx教程(一) Nginx入门教程 (转)
1 Nginx入门教程 Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like协议下发行.由俄罗斯的程序设计师IgorSysoev所开 ...
- 洛谷 P1119 灾后重建 最短路+Floyd算法
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例 输出样例 说明 思路 AC代码 总结 题面 题目链接 P1119 灾后重建 题目描述 B地区在地震过后,所有村 ...
- MUI - 封装localStorage与plus.storage
MUI - 封装localStorage与plus.storage 2.0版本 在使用plus.storage频繁地存取数据时,可以感觉到明显的卡顿,而且很耗内存, 在切换到localstorage时 ...