W同学的新画板 QDUOJ 线段树 区间颜色段数
时间:2019-10-10
本文章向大家介绍W同学的新画板 QDUOJ 线段树 区间颜色段数,主要包括W同学的新画板 QDUOJ 线段树 区间颜色段数使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
W同学的新画板 QDUOJ 线段树 区间颜色段数
题意
W同学在每天的刻苦学习完成功课之余,都会去找一些有趣的事情来放松自己;恰巧今天他收到了朋友送给他的一套画板,于是他立刻拆开了包装,拿出其中的画板和一些画笔,开心地画了起来;这时W同学注意到了闲暇的你正好待在一旁,于是他灵机一动,打算考验一下你的眼力,具体过程是这样的:
W同学收到的画板可看作一个长条状的木板,画板从左端到右端可划分为等长的连续的n段(自左至右依次编号为第1段,第2段,第3段,...,第n段,如下图所示),开始时每一段都有一个初始的颜色,之后W同学会进行一些操作,每次操作中他都会选一段区间[L,R],然后用画笔把画板的第L段~第R段这一块连续的部分染为颜色C(被染色的某段先前已存在的颜色会被新颜色覆盖),而且每当进行一些染色操作后,W同学都有可能会让你立即答出他给你的某段区间[L,R]中共有多少个颜色段,以此考察你的眼力,聪明的你敢不敢接受W同学的考验?
解题思路
使用线段树来进行处理这个题是大体的思路,原因在于题目要求一段区间内的颜色段数。要注意的是,这里是求取一段区间内的颜色的段数,不是有多少种颜色,比如 1 2 2 1 1 这个画板就有3段颜色,和自己以前做的求取区间内的颜色的种类数不同,这个题目还没想过,确实很新,参考的CH大佬的代码,下方链接。
代码实现(带注释)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=5e5+7;
struct Node{
int l, r;
int sum, lazy;//sum记录这里有几段颜色段,lazy就是线段树常用的标记
int le, re; //这里是来记录这段区间的左右端点处的颜色种类
}node[maxn<<2];
int col[maxn]; //存储初始的颜色种类
void up(int rt)
{
node[rt].sum=node[rt<<1].sum+node[rt<<1|1].sum; //左右区间段数相加
if(node[rt<<1].re==node[rt<<1|1].le)//这里需要注意左右段的交界处,如果相等的话,总的段数是要进行减一的
node[rt].sum--; //这里想一想是不是
node[rt].le=node[rt<<1].le;
node[rt].re=node[rt<<1|1].re;
}
void build(int rt, int l, int r)
{
node[rt].l=l;
node[rt].r=r;
node[rt].lazy=-1;
if(l==r)
{
node[rt].sum=1;
node[rt].le=node[rt].re=col[l];
return ;
}
int mid=(l+r)>>1;
build(rt<<1, l, mid);
build(rt<<1|1, mid+1, r);
up(rt);
}
void down(int rt)
{
node[rt<<1].lazy=node[rt<<1|1].lazy=node[rt].lazy;
node[rt<<1].sum=node[rt<<1|1].sum=1; //左右的段数都归为1
node[rt<<1].le=node[rt<<1].re=node[rt].lazy;
node[rt<<1|1].le=node[rt<<1|1].re=node[rt].lazy;
node[rt].lazy=-1;
}
void update(int rt, int l, int r, int v)
{
if(l <= node[rt].l && node[rt].r <= r)
{
node[rt].lazy = node[rt].le = node[rt].re = v;
node[rt].sum=1;
return ;
}
int mid=(node[rt].l+node[rt].r)>>1;
if(node[rt].lazy!=-1) //这里有点不一样
down(rt);
if(l<=mid) update(rt<<1, l, r, v);
if(r>mid) update(rt<<1|1, l, r, v);
up(rt);
}
int query(int rt, int l, int r)
{
if(l <= node[rt].l && node[rt].r <=r)
{
return node[rt].sum;
}
if(node[rt].lazy!=-1)
down(rt);
int ans=0, mid=(node[rt].l + node[rt].r)>>1;
//这里因为交界处的特殊性,所以询问的方式不再是if(l<=mid)……然后if(r>mid)……
//这里需要判断三种情况
//1.全部在左区间 2.全部在右区间 3.左右区间都有
//这里1,2种情况比较好处理,就是第3种情况需要特殊一些
//第三种情况也是分开两半来计算的,但是需要判断中间交汇处是不是需要进行减一
if(r<=mid) return query(rt<<1, l, r); //第一种情况
else if(l>mid) return query(rt<<1|1, l, r); //第二种情况
else ans=query(rt<<1, l, r)+query(rt<<1|1, l, r); //第三种情况,也是比较特殊的一种情况
if(node[rt<<1].re == node[rt<<1|1].le)//这是关键,判断中间交汇处的颜色是不是相等,相等需要减一
ans--;
return ans;
}
int main()
{
int n, q, op, a, b, c;
cin>>n>>q;
for(int i=1; i<=n; i++)
cin>>col[i];
build(1, 1, n);
for(int i=1; i<=q; i++)
{
cin>>op;
if(op==1)
{
cin>>a>>b>>c;
update(1, a, b, c);
}
else if(op==2)
{
cin>>a>>b;
cout<<query(1, a, b)<<endl;
}
}
return 0;
}
原文地址:https://www.cnblogs.com/alking1001/p/11650323.html
- MySQL Tips【Updating】
- Meltdown、Spectre攻击---CPU乱序执行和预测执行导致的安全问题
- WordPress 4.6远程代码执行漏洞(CVE-2016-10033)复现环境搭建指南
- 相似文档查找算法之 simHash 简介及其 java 实现
- Hadoop 中利用 mapreduce 读写 mysql 数据
- Android O中对TEE加解密算法的新要求
- storm 原理简介及单机版安装指南
- Python Tips, Tricks, and Hacks
- 英特尔放出Linux微代码以修复Meltdown和Spectre漏洞
- python基础(5):深入理解 python 中的赋值、引用、拷贝、作用域
- Linux SSH密码暴力破解技术及攻防实战
- 西部数据NAS设备被曝存在硬编码后门和未授权文件上传高危漏洞
- Hive & Performance 学习笔记
- 任意用户密码重置(一):重置凭证泄漏
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 01 . PostgreSQL简介部署
- 01 . Git常用命令及方法和分支管理
- 记一次公司mssql server密码频繁被改的事件
- elasticsearch 同义词更新,不同集群返回更新节点个数不一样
- H5应用加固防破解-js虚拟机保护方案浅谈
- struts2概述
- 移动端适配解决方案
- struts2(一)---编写第一个struts2项目
- Struts2(二)---将页面表单中的数据提交给Action
- 03 . Shell数组和函数
- Shell百宝箱(后续会不断更新)
- 09 . Prometheus监控tomcat+jvm
- 09 . Kubernetes之pv、pvc及使用nfs网络存储应用
- 10 . Kubernetes之Configmap,Secret
- struts2(三)---使用EL表达式,显示Action中的数据