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 ...
随机推荐
- python中bisect模块的使用
一般用于二分查找, 当然列表应该是有序表 参考于: http://blog.csdn.net/xiaocaiju/article/details/6975714
- 2018-5-4-WPF-获得触摸精度和触摸点
title author date CreateTime categories WPF 获得触摸精度和触摸点 lindexi 2018-05-04 21:11:51 +0800 2018-5-4 21 ...
- HDU4251-The Famous ICPC Team Again(划分树)
Problem Description When Mr. B, Mr. G and Mr. M were preparing for the 2012 ACM-ICPC World Final Con ...
- day39-Spring 03-JDK的动态代理
package cn.itcast.spring3; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Meth ...
- @codeforces - 932G@ Palindrome Partition
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个字符串 s,求有多少种方案可将其划分成偶数个段 \(p_ ...
- 笔记:字体大小的几种不同的格式px,em,rem
px px像素(Pixel),相对长度单位,像素px是相对于显示器屏幕分辨率而言的.(引自CSS2.0手册) 譬如,Windows的用户所使用的分辨率一般是96像素/英寸. 而MAC的用户所使用的分辨 ...
- jq获取浏览器可视窗口的高度
<script> var window_height = $(window).height(); </script>
- IDEA-创建WEB项目并部署Tomcat
一.创建简单web项目 1.创建一个web project File -> new Project ->选择project sdk 为1.6(如果没有sdk的同学请先配置)-> Ne ...
- 线段树动态开点+树链剖分BZOJ4999
以每个一个颜色开一颗线段树,内部以dfs序作为线段树节点,权值代表出现次数,维护线段树区间和 #include<iostream> #include<stdio.h> #inc ...
- MySQL 获取当前月的天数
select curdate(); --获取当前日期 select DATE_ADD(curdate(),interval -day(curdate())+ ...