前言

本蒟蒻重学线段树,发现了这道题可以用线段树做。

虽然数据范围很小可以直接暴力,但由于在练习线段树所以打算用线段树写这道题。

本题解针对已经有线段树基础的巨佬,不懂线段树原理的话可以学习线段树后再阅读本题解。

审题

刚看题的时候以为大概是个线段树模板,结果发现事情并不简单。

题目要求的不是剩下多少棵树和砍掉了多少棵树木,而是要求剩下和砍掉了多少棵树苗

并且需要注意区间是从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 校门外的树(增强版)的更多相关文章

  1. 洛谷——P1276 校门外的树(增强版)

    P1276 校门外的树(增强版) 题目描述 校门外马路上本来从编号0到L,每一编号的位置都有1棵树.有砍树者每次从编号A到B处连续砍掉每1棵树,就连树苗也不放过(记 0 A B ,含A和B):幸运的是 ...

  2. Luogu P1276 校门外的树(增强版)

    Luogu P1276 校门外的树(增强版) 本来看着是道普及-,就不打算写博客了,结果因为出了3次错,调试了15min就还是决定写一下-- 本题坑点: 1.每个位置有三种情况:空穴,树苗,树(而不只 ...

  3. 洛谷 P1276 校门外的树(增强版)

    题目描述 校门外马路上本来从编号0到L,每一编号的位置都有1棵树.有砍树者每次从编号A到B处连续砍掉每1棵树,就连树苗也不放过(记 0 A B ,含A和B):幸运的是还有植树者每次从编号C到D 中凡是 ...

  4. 洛谷P1276 校门外的树(增强版)未完工

    题目描述 校门外马路上本来从编号0到L,每一编号的位置都有1棵树.有砍树者每次从编号A到B处连续砍掉每1棵树,就连树苗也不放过(记 0 A B ,含A和B):幸运的是还有植树者每次从编号C到D 中凡是 ...

  5. 洛谷题解P1047 校门外的树

    题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,…,L,都种有 ...

  6. Vijos1448校门外的树 题解

    Vijos1448校门外的树 题解 描述: 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现 ...

  7. >题解< 校门外的树

    题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是 11 米.我们可以把马路看成一个数轴,马路的一端在数轴 00 的位置,另一端在 LL 的位置:数轴上的每个整数点,即 0,1 ...

  8. 【解题报告】VijosP1448校门外的树(困难版)

    原题: 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的--如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:K=1,K=1,读入l.r ...

  9. JDOJ 2197: 校门外的树

    JDOJ 2197: 校门外的树 题目传送门 Description 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米. 我们可以把马路看成一个数轴,马路的一端在数轴1的位置,另一 ...

随机推荐

  1. 推荐简约漂亮的小程序插件 calendar

    公司团队制作,主要用于内部使用,觉得这个感觉不错,所以推荐出来,让大家试试~ 日历功能 日历基本功能,自定义样式 先睹为快 使用方法: 1. 在微信小程序管理后台--设置--第三方服务,按 AppID ...

  2. 学习如何运用GitHub网站+出现的问题+Git基本操作总结

    首先介绍一下GitHub网站: github是一个基于git的代码托管平台. GitHub 拥有一个非常鼓励合作的社区氛围.这一方面源于 GitHub 的付费模式:私有项目需要付费,而公共项目完全免费 ...

  3. 存储过程 psal emp.sal%type是什么意思

    psal emp.sal%type 就是指psal这个变量是引用了表emp中的sal字段的类型.如果emp表中sal的类型变了,psal这个字段的类型也会跟着变化,总之,psal和表emp中sal字段 ...

  4. iframe引入微信公众号文章

    微信在文章页面设置了响应头""frame-ancestors 'self'"阻止了外部页面将其嵌套的行为,文章的图片也设置了防盗链的功能,这就导致了直接在iframe中引 ...

  5. JavaScript一些重要知识点结合题目的表现!

    function Foo() { //① 声明一个Foo的函数 getName = function () { alert (1); }; return this; } Foo.getName = f ...

  6. 实际业务处理 Kafka 消息丢失、重复消费和顺序消费的问题

    关于 Kafka 消息丢失.重复消费和顺序消费的问题 消息丢失,消息重复消费,消息顺序消费等问题是我们使用 MQ 时不得不考虑的一个问题,下面我结合实际的业务来和你分享一下解决方案. 消息丢失问题 比 ...

  7. Golang | 并发

    goroutine 协程(Coroutine) Golang 在语言层面对并发编程进行了支持,使用了一种协程(goroutine)机制, 协程本质上是一种用户态线程,不需要操作系统来进行抢占式调度,但 ...

  8. vue3组合式API

    vue3组合式API 为什么要用组合式API,我们来看看它是如何解决vue2的局限性的 1.vue2的局限性 当组件内容越来越多,逻辑越来越复杂,可读性就会降低,并且难以维护. vue2组件采用配置式 ...

  9. Codeforces Round #752 (Div. 2) A B C

    Problem - A - Codeforces Problem - B - Codeforces Problem - C - Codeforces A. Era 每个a[i] - i 表示的是当前a ...

  10. 一款开源的文件搜索神器,终于不用记 find 命令了

    这是 HelloGitHub 推出的<讲解开源项目>系列,用一篇文章带你快速上手有趣的开源项目. 今天给大家推荐一个好用+开源的文件搜索工具--fd 该工具支持大多数主流操作系统,快来更新 ...