题解 P1276 校门外的树(增强版)
前言
本蒟蒻重学线段树,发现了这道题可以用线段树做。
虽然数据范围很小可以直接暴力,但由于在练习线段树所以打算用线段树写这道题。
本题解针对已经有线段树基础的巨佬,不懂线段树原理的话可以学习线段树后再阅读本题解。
审题
刚看题的时候以为大概是个线段树模板,结果发现事情并不简单。
题目要求的不是剩下多少棵树和砍掉了多少棵树木,而是要求剩下和砍掉了多少棵树苗。
并且需要注意区间是从0开始的。
那么注意到这些差不多就可以开始想做法了。
解决
因为种树人每次种树种植的都是树苗,所以只有最初的区间上会有一整个区间的树木。所以我们可以对于树木建立一棵线段树,再对于树木和树苗共同建立一棵线段树。这样在砍树的时候分别查询两棵线段树并且进行差分,就可以得到区间上砍掉的树苗的数量。最后查询整个区间上树苗个数同理
其中线段树需要支持的操作
- 区间赋值
- 区间加查询
Code
那么具体实现代码如下:
#include<bits/stdc++.h>
using namespace std;
#define file(a) freopen(#a".in","r",stdin),freopen(#a".out","w",stdout)
#define LL long long
#define N 10010
int n,m;
struct node_tree
{
int l,r,mid;
int vol,d;//vol是赋值的lazy标记
};
struct tree//为了方便维护两棵线段树,于是开了结构体
{
node_tree t[N*4];
void build(int i,int l,int r)//建树,本质上是初始化
{
t[i].l=l;t[i].r=r;t[i].mid=(l+r)>>1;
t[i].d=0;t[i].vol=-1;
if(l==r)
{
t[i].d=0;;
return;
}
build(i<<1,l,t[i].mid);
build(i<<1|1,t[i].mid+1,r);
t[i].d=(t[i<<1].d+t[i<<1|1].d);
return;
}
void pushdown(int i)
{
if(!(~t[i].vol)) return;
//这里是防止赋值上初始化值,因为(~(-1))==0
t[i<<1].vol=t[i].vol;
t[i<<1|1].vol=t[i].vol;
t[i<<1].d=t[i].vol*(t[i<<1].r-t[i<<1].l+1);
t[i<<1|1].d=t[i].vol*(t[i<<1|1].r-t[i<<1|1].l+1);
t[i].vol=-1;
return;
}
void modify_vol(int i,int l,int r,int k)//区间赋值
{
if(l<=t[i].l&&t[i].r<=r)
{
t[i].d=k*(t[i].r-t[i].l+1);
t[i].vol=k;
return;
}
pushdown(i);
if(l<=t[i].mid) modify_vol(i<<1,l,r,k);
if(t[i].mid+1<=r) modify_vol(i<<1|1,l,r,k);
t[i].d=(t[i<<1].d+t[i<<1|1].d);
return;
}
int query(int i,int l,int r)//查询区间和
{
if(l<=t[i].l&&t[i].r<=r)
{
return t[i].d;
}
pushdown(i);
int res=0;
if(l<=t[i].mid) res+=query(i<<1,l,r);
if(t[i].mid+1<=r) res+=query(i<<1|1,l,r);
return res;
}
}t1,t2;//t1存树木 t2存树苗加树木
int ans1,ans2;
int main()
{
scanf("%d%d",&n,&m);
t1.build(1,0,n);t2.build(1,0,n);
t1.modify_vol(1,0,n,1);t2.modify_vol(1,0,n,1);//初始化
while(m--)
{
int opt,l,r;
scanf("%d%d%d",&opt,&l,&r);
if(!opt)
{
ans2+=t2.query(1,l,r)-t1.query(1,l,r);
t1.modify_vol(1,l,r,0);
t2.modify_vol(1,l,r,0);
}
if(opt)
{
t2.modify_vol(1,l,r,1);
}
/*
这个是线段树调试(可以忽略)
for(int i=0;i<=n;++i)
{
printf("%d(%d)[%d] ",t2.query(1,i,i),t1.query(1,i,i),i);
}
putchar('\n');
*/
}
ans1=t2.query(1,0,n)-t1.query(1,0,n);
printf("%d\n%d",ans1,ans2);
return 0;
}
题解 P1276 校门外的树(增强版)的更多相关文章
- 洛谷——P1276 校门外的树(增强版)
P1276 校门外的树(增强版) 题目描述 校门外马路上本来从编号0到L,每一编号的位置都有1棵树.有砍树者每次从编号A到B处连续砍掉每1棵树,就连树苗也不放过(记 0 A B ,含A和B):幸运的是 ...
- Luogu P1276 校门外的树(增强版)
Luogu P1276 校门外的树(增强版) 本来看着是道普及-,就不打算写博客了,结果因为出了3次错,调试了15min就还是决定写一下-- 本题坑点: 1.每个位置有三种情况:空穴,树苗,树(而不只 ...
- 洛谷 P1276 校门外的树(增强版)
题目描述 校门外马路上本来从编号0到L,每一编号的位置都有1棵树.有砍树者每次从编号A到B处连续砍掉每1棵树,就连树苗也不放过(记 0 A B ,含A和B):幸运的是还有植树者每次从编号C到D 中凡是 ...
- 洛谷P1276 校门外的树(增强版)未完工
题目描述 校门外马路上本来从编号0到L,每一编号的位置都有1棵树.有砍树者每次从编号A到B处连续砍掉每1棵树,就连树苗也不放过(记 0 A B ,含A和B):幸运的是还有植树者每次从编号C到D 中凡是 ...
- 洛谷题解P1047 校门外的树
题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,…,L,都种有 ...
- Vijos1448校门外的树 题解
Vijos1448校门外的树 题解 描述: 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现 ...
- >题解< 校门外的树
题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是 11 米.我们可以把马路看成一个数轴,马路的一端在数轴 00 的位置,另一端在 LL 的位置:数轴上的每个整数点,即 0,1 ...
- 【解题报告】VijosP1448校门外的树(困难版)
原题: 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的--如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:K=1,K=1,读入l.r ...
- JDOJ 2197: 校门外的树
JDOJ 2197: 校门外的树 题目传送门 Description 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米. 我们可以把马路看成一个数轴,马路的一端在数轴1的位置,另一 ...
随机推荐
- web项目中视频的上传和展示
思路: 上传:<form>表单提交视频-->后台使用字节流保存到本地. 展示:<video>标签展示: src属性发送请求 --> 使用字节流将视频绑定到响应并返回 ...
- [护网杯 2018]easy_tornado 1
复现一道关于tornado的题目 首先可以得知此题用的是tornado,基于python的后端框架,多半是ssti注入 有三个文件,首先可得知flag在何处 然后观察hint和url就知道要根据coo ...
- python-验证6174猜想
[题目描述]1955年,卡普耶卡(D.R.Kaprekar)对4位数字进行了研究,发现一个规律:对任意各位数字不相同的4位数,使用各位数字能组成的最大数减去能组成的最小数,对得到的差重复这个操作,最终 ...
- Java/C++实现命令模式---多次撤销和撤回
某系统需要提供一个命令集合(注:可以使用链表,栈等集合对象实现),用于存储一系列命令对象,并通过该命令集合实现多次undo()和redo()操作,可以使用加法运算来模拟实现.\ 类图: Java代码: ...
- JS中Map和ForEach的区别
定义 forEach()方法: 针对每一个元素执行提供的函数. map()方法: 创建一个新的数组,其中每一个元素由调用数组中的每一个元素执行提供的函数得来. 区别 forEach()方法不会返回执行 ...
- C++五子棋(四)——走棋原理及权值计算
原理 计算 计算每个落子点的**"权值"**,找到权值最大的落子点 对于每个空白点,分别计算周围的八个方向 不妨以该空白点作为参照原点,以水平向右作为X轴正方向,以竖直向下为Y轴正 ...
- 使用加强堆结构解决topK问题
作者:Grey 原文地址: 使用加强堆结构解决topK问题 题目描述 LintCode 550 · Top K Frequent Words II 思路 由于要统计每个字符串的次数,以及字典序,所以, ...
- 【Azure API 管理】解决API Management添加AAD Group时遇见的 Failed to query Azure Active Directory graph due to error 错误
问题描述 为APIM添加AAD Group时候,等待很长很长的时间,结果添加失败.错误消息为: Write Groups ValidationError :Failed to query Azure ...
- python基础练习题(题目 一个数如果恰好等于它的因子之和,这个数就称为"完数"。例如6=1+2+3.编程找出1000以内的所有完数)
day12 --------------------------------------------------------------- 实例019:完数 题目 一个数如果恰好等于它的因子之和,这个 ...
- Kafka生成消息时的3种分区策略
摘要:KafkaProducer在发送消息的时候,需要指定发送到哪个分区, 那么这个分区策略都有哪些呢? 本文分享自华为云社区<Kafka生产者3中分区分配策略>,作者:石臻臻的杂货铺. ...