Vijos1448校门外的树 题解

描述:
校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……
如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:
K=1,K=1,读入l、r表示在区间[l,r]中种上一种树,每次操作种的树的种类都不同
K=2,读入l,r表示询问l~r之间能见到多少种树
(l,r>0)
 
输入格式:
第一行n,m表示道路总长为n,共有m个操作
接下来m行为m个操作
 
输出格式:
对于每个k=2输出一个答案
 
样例输入:
5 4
1 1 3
2 2 5
1 2 4
2 3 5
 
样例输出:
1
2
 
数据范围:
20%的数据保证,n,m<=100
60%的数据保证,n <=1000,m<=50000
100%的数据保证,n,m<=50000
 
 
~~~~~~~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
分析:
这道题是一个典型的区间问题,考虑到数据量较大,使用线段树完成这个操作。由于树的种类很多,不难想到用线段树暴力维护的方法。但是暴力维护一定会超时,那么这么解决这个问题呢?
这里介绍一种十分机智的想法——括号序列
假设有一个长度为10的数轴,我们要将区间[ 2 , 5 ]中种树,这时,我们将 2 处放一个左括号 " ( "  ,5处放一个 " )"  ,表示区间 [ 2 , 5 ]种了树。
查询某个区间树的种类,如区间[ 3 , 10],只需统计10之前(包括10)有多少个‘(’,统计3之前有多少个‘)’,(不包括3)。  
如下图所示:

以上就是括号序列的过程。简单的说,就是更新区间[a,b]时,点a记录左括号数,点b记录右括号数,查询区间[a,b]时,即为b之前(包括b)的左括号数-a之前的右括号数。
 
下面贴注释代码:

 #include "bits/stdc++.h"
#define maxN 50010 using namespace std ;
typedef long long QAQ ; struct Tree
{
int l , r ;
QAQ liml , limr ;//左括号右括号
}; Tree tr[maxN << ]; void Build_Tree ( int x , int y , int i )//建树
{
tr[i].l = x ;
tr[i].r = y ;
if( x == y )return ;
else
{
QAQ mid = (tr[i].l + tr[i].r) >> ;
Build_Tree ( x , mid , i << );
Build_Tree ( mid + , y , i << | );
return ;
}
} void Update_left ( int w , int i )
{
if( w == tr[i].l && w == tr[i].r )tr[i].liml++;//找到目标节点
else
{
QAQ mid = (tr[i].l + tr[i].r) >> ;
if( w > mid )Update_left( w , i << | );//找右儿子
else if( w <= mid)Update_left( w , i << );//找左儿子
tr[i].liml = tr[i << ].liml + tr[i << | ].liml ;//回溯更新
}
} void Update_right ( int w , int i )//同Update_left
{
if( w == tr[i].l && w == tr[i].r )tr[i].limr++;
else
{
QAQ mid = (tr[i].l + tr[i].r) >> ;
if( w > mid )Update_right( w , i << | );
else if( w <= mid)Update_right( w , i << );
tr[i].limr = tr[i << ].limr + tr[i << | ].limr ;
}
} QAQ Query_left ( int q , int w , int i )//同Query_right
{
if( q <= tr[i].l && w >= tr[i].r )return tr[i].liml ;
else
{
QAQ mid = (tr[i].l + tr[i].r) >> ;
if ( q > mid )return Query_left ( q , w , i << | );
else if ( w <= mid ) return Query_left ( q , w , i << );
else return Query_left ( q , w , i << | ) + Query_left ( q , w , i << );
}
} QAQ Query_right ( int q , int w , int i )
{
if( q <= tr[i].l && w >= tr[i].r )return tr[i].limr ;//找到目标区间直接返回
else
{
QAQ mid = (tr[i].l + tr[i].r) >> ;
if ( q > mid )return Query_right ( q , w , i << | );//找右儿子
else if ( w <= mid ) return Query_right ( q , w , i << );//找左儿子
else return Query_right ( q , w , i << | ) + Query_right ( q , w , i << );//左右儿子都查找
}
} int main()
{
int N, M, op, ll, rr ;
scanf("%d %d", &N, &M);
Build_Tree ( , N , ) ;//建树
while(M--)
{
scanf("%d%d%d", &op, &ll, &rr);
if( op == )
{
Update_left ( ll , );//添加左括号
Update_right ( rr , );//添加右括号
}
else
{
QAQ ans = Query_left( , rr , );
if (ll != )ans -= Query_right( , ll - , );//当ll不等于1时再相减,否则栈会炸
printf("%I64d\n", ans);
}
}
return ;
}
 PS: 本题也可以用树状数组完成,代码量较少,容易实现。
 
 (完)
 

Vijos1448校门外的树 题解的更多相关文章

  1. Vijos1448 校门外的树 [树状数组]

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

  2. vijos1448校门外的树

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

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

    题目 此题是一个模拟题,但需要注意的一点就是它的树是从数轴的0开始,所以我们也要从0开始,这样才能实现代码. 代码: #include<iostream> using namespace ...

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

    Case 1. 本题其实不难,直接模拟就可以了.时间复杂度: \(O(L \times M)\) Case 2. 考虑一个简单的增强:把原来的: \[L \leq 10^4,M \leq 10^2 \ ...

  5. >题解< 校门外的树

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

  6. JDOJ 2197: 校门外的树

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

  7. NC16649 [NOIP2005]校门外的树

    NC16649 [NOIP2005]校门外的树 题目 题目描述 某校大门外长度为 \(L\) 的马路上有一排树,每两棵相邻的树之间的间隔都是 \(1\) 米.我们可以把马路看成一个数轴,马路的一端在数 ...

  8. P1047 校门外的树

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

  9. OpenJudge计算概论-校门外的树

    /*======================================================================== 校门外的树 总时间限制: 1000ms 内存限制: ...

随机推荐

  1. Java集合源码学习(三)LinkedList分析

    前面学习了ArrayList的源码,数组是顺序存储结构,存储区间是连续的,占用内存严重,故空间复杂度很大.但数组的二分查找时间复杂度小,为O(1),数组的特点是寻址容易,插入和删除困难.今天学习另外的 ...

  2. Java 解析XML的几种方法

    XML现在已经成为一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便. XML在不同的语言里解析方式都是一样的,只不过实现的语法不同而已. 基本的解析方式 ...

  3. sqlplus 中spool命令的简单用法

    spool基本格式: spool 路径+文件名 select col1||','||col2||','||col3||','||col4||'..' from tablename; spool off ...

  4. Python 入门简介(一)

    Why Python? 我个人认为去学习一门新的语言其实是不需要理由的,当然如果你硬要我编个理由的话还是很容易的. 容易学 容易用 有人真的在用Python么? 这个问题谁用谁知道. 选择什么开发工具 ...

  5. Zero Copy 简介

    转自:http://blog.csdn.net/zzz_781111/article/details/7534649 许多web应用都会向用户提供大量的静态内容,这意味着有很多data从硬盘读出之后, ...

  6. 第二篇:SOUI源码的获取及编译

    源代码的获取 SOUI的源码采用SVN管理. SVN:http://code.taobao.org/svn/soui2 这里主要包含两个目录:trunk 及 third-part. trunk目录保存 ...

  7. PRD产品需求文档

    什么是PRD? PRD是Product Requirement Document的英文缩写,即产品需求文档的意思.PRD昰产品流程中的最后一步工作,是将原型中的功能.界面具象化描述,是提交给设计(UI ...

  8. zTree学习文档和DEOM

    http://tool.oschina.net/apidocs/apidoc?api=ztree3.2%2Fapi%2FAPI_cn.html zTree的API http://www.ztree.m ...

  9. flex_高度补全

    一个高度为100px, 另外一个高度自动补全当前界面下剩余的高度: <!DOCTYPE html> <html lang="en"> <head> ...

  10. centos7安装redis3.2.5

    安装redis 1官方介绍 Installation Download, extract and compile Redis with: $ wget http://download.redis.io ...