线段树专题new

合集下载

线段树讲解(数据结构、C++)

线段树讲解(数据结构、C++)

线段树讲解(数据结构、C++)声明:仅⼀张图⽚转载于,⾃⼰画太⿇烦了。

那个博客的讲解也很好,只是他⽤了指针的⽅式来定义线段树,⽽我⽤了结构体,并且他讲了线段树的更⾼级的操作,若对线段树的初级操作不理解,请继续阅读线段树作为⼀种⼗分常⽤的数据结构,在NOIP、NOI中⼴泛的出现,所以在这⾥对线段树进⾏简单的讲解。

线段树⽀持对⼀个数列的求和、单点修改、求最值(最⼤、最⼩)、区间修改(需要lazy标记,暂不讲解)。

这⼏种操作,时间复杂度是(logn)级别的,是⼀种⼗分优秀的数据结构。

因此其获得了⼴泛的应⽤。

定义:顾名思义,它是⼀种树形结构,但每段不是平常所学的⼀个点⼀个点的树,⽽是⼀条⼀条的线段,每条线段包含着⼀些值,其中最主要的是起始和结束点记作 l,r 即左端点和右端点。

那么该如何划分线段树呢?我们采⽤⼆分的思想,即每次将⼀段取半,再进⾏接下来的操作,这样综合了操作的⽅便程度和时间复杂度。

因为线段树通过⼆分得来,所以线段树是⼀颗⼆叉树。

这也⽅便了对⼉⼦查找。

下⾯是线段树的图,有利于理解:建树:仅仅知道模型还是不够的,建树的过程是线段树的关键(build(1,1,n))从⼀号开始,左端是1,右端是n位运算 i<<1 等效于 i/2 (i<<1)|1 等效于 i/2+1 加速。

inline void update(int i)更新i节点维护的值(求和,最⼤……){node[i].sum=node[i<<1].sum+node[(i<<1)|1].sum;node[i].maxx=max(node[i<<1].maxx,node[(i<<1)|1].maxx);}inline void build(int i,int l,int r)//inline 还是加速{node[i].l=l;node[i].r=r;//左右端点为当前递归到的 l 和 rif(l==r){//若l==r 则当前的树节点是真正意义上的点node[i].maxx=a[l];//最⼤值就是本⾝的值node[i].sum=a[l];//区间的和就是本⾝的值return;}int mid=(l+r)/2;//因为是⼆叉树所以以中点为分割点build(i<<1,l,mid);//根据⼆叉树的知识,左⼉⼦是i/2右⼉⼦是i/2+1build((i<<1)|1,mid+1,r);update(i);}数列求和:这是线段树的⼀个典型算法,其他的很多应⽤都是从中转化的。

线段树讲解

线段树讲解

关于线段树数据结构的研究线段树(Segment Tree)是一种高级的数据结构,顾名思义,它既是线段也是树,并且是一棵二叉树。

线段树的每个节点是一条线段[a,b],每条线段的左右儿子线段分别是该线段的左半区间[a,(a+b)/2]和右半区间[(a+b)/2+1,b],递归定义之后就是一棵线段树。

因此,线段树是平衡二叉树,且最后的叶子节点数为N,即整个线段区间的长度。

要知道,在不同的题目中,线段可以有不同的含义,如数轴上的一条真实的线段,或者是一个序列的连续子序列。

使用线段树可以快速地查找某一节点在若干条线段中出现的次数,时间复杂度是O(logN)。

图示如下:[1,8]/ \[1,4] [5,8]/ \ / \[1,2] [3,4] [5,6] [7,8]/ \ / \ / \ / \[1,1] [2,2] [3,3 ] [4,4] [5,5][6,6] [7,7] [8,8]线段树有以下操作:⑴区间查询询问某段区间的某些性质(极值,求和)⑵区间更新某些操作影响了某段区间(统一加了一个值)⑶三个问题①更新点,查询区间②更新区间,查询点③更新区间,查询区间定义线段树的数据结构Struct tree{Int left, right; //区间的端点Int max, sum; //视题目要求而定,重点维护的信息}tree[N*4]; //线段树空间应为原数组长度的4倍我们用一个一维的结构体数组tree[N*4]来记录节点,且根节点的下标为1,则对于任意非叶子节点tree[k],它的左二子为tree[2*k],它的右儿子为tree[2*k+1].线段树的代码实现(建树)V oid build (int id, int l, int r){Tree[id],left=l;Tree[id].right=r;If(l==r)Tree[id].sum=l;Tree[id].max=l;Else{Int mid=(l+r)/2;Build(id*2, l, r);Build(id*2+1, l, r);Tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;Tree[id].max=max(tree[id*2].max,tree[id*2+1].max);}} // 如果原数组从a[1]~a[n],调用build(1, 1, n)即可线段树的点更新V oid update (int id, int pos, int val ){If(tree[id].left==tree[id].right)Tree[id].sum=val;Else{Int mid=(tree[id].left+tree[id].right)/2;If(pos<=mid)Update(id*2, pos, val);ElseUpdate(id*2+1, pos, val);Tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;}}线段树的查询int query (int id, int l, int r){if(tree[id].left==l&&tree[id].right==r)return tree[id].sum;else{int mid=(tree[id].left+tree[id].right)/2;if(r<=mid)return query(id*2, l, r); // 待查区间在其左子区间中else if(l>mid)return query(id*2+1, l, r); // 待查区间在其右子区间中else return query(id*2, l, mid)+query(id*2+1, mid+1, r);//待查区间横跨其左右子区间}}很多时候,将问题建模成数轴上的问题或是数列上的问题后,具体地操作一般是每次对数轴上的一个区间或是数列中的连续若干个数进行一种相同的处理,比如统一加上一个数,如果处理只针对各个元素逐个进行,导致算法的效率较低。

线段树

线段树
பைடு நூலகம்
• QUERY: 把所有直系祖先的a值相加, 就是 A[i]的增加量
继续讨论
• 附加信息a(p)到底是什么?
– 首先要在同一条指令中被增加 – 但在同一条指令中被增加的结点却不能都被修 改, 否则ADD(1, n)仍然要修改所有结点 – 正确的理解是: 先把指令ADD分解为不超过 2log2L条指令, 每条指令的区间[i, j]都在树中有 单一的结点与之对应, 然后每条原子ADD操作 单一的结点 只修改该结点本身的计数器
[1,2] 1 2 [1,4] [3,4] 3 4 [1,9] [5,9] [5,6] 5 6 [7,9] 7 [8,9] 8 9
和应用相关的几个小问题
• 线段长度为偶数: 左小右大还是左大右小 • 一样大 • 原始线段长度不是2的幂: 允许不平均分割还是补 齐到2的幂? • (允许不平均分割) • 叶子是单个元素i还是单位线段[i, i+1]? • (是单个元素) • 静态 or 动态?(静态) • 建立: 自顶向下递归分割还是自底向上合并? • 分割合并都可以
• 增加区间时进行分解, 设置计数器c(p), 表示 分解后指令Add(x, y)的条数
覆盖长度可以维护么?
• 考虑根结点. 如果c(root)>0, 则整个区间都 被覆盖, 返回L, 但如果c(root)=0呢? 需要根 据左右儿子递推 • 是否可以定义l(p), 表示结点p对应的区间内 被覆盖到的总长度呢? 不可以!
– 得到讨论区间(可能要先离散化) – 设计区间附加信息和维护/统计算法
• 线段树自身没有任何数据, 不像BST一样有 一个序关系 • 警告 想清楚 警告: 想清楚附加信息的准确含义 不能有 准确含义, 准确含义 半点含糊! 便于解题的附加信息,如果难 • 建议 先设计便于解题 建议: 便于解题 以维护就加以修改

线段树

线段树
h log(2n 1) O(log n) 。
对于线段树中的每个结点, 其表示一个区间,我们可以记录和这个区间相关 的一些信息(如最大值、最小值、和等) ,但要满足可二分性,即能直接由其子
结点的相关信息得到。 对于询问区间信息和修改区间信息的操作,线段树一般在能 O(log n) 的时间 内完成,而且常数相对较小(和后面的伸展树比较) ,算是一种高效实用的数据 结构。 (2)线段树的基本操作——查询区间信息 使用线段树的目的就是能高效地查找和修改区间信息, 下面先介绍第一个操 作——查询操作。 对于当前要查询的区间 a, b ,我们从线段树的根结点开始,如果当前结点 表示的区间被查询区间完全包含,那么更新结果,否则分别考察左右子结点,如 果查询区间与某个子结点有交集(也可能两个都有) ,那么就递归考察这个子结 点。代码框架如下1:
对于任意一个区间,会被划分成很多在线段树上存在的区间,可以证明,划 分出来的区间在线段树的每层最多有两个,又因为线段树的深度为 O(log n) ,因 此查询操作的时间复杂度为 O(log n) 。
(3)线段树的基本操作——修改区间信息 相对于查询区间信息,修改区间信息显得稍微复杂一些。
1
本文中的代码均使用 C++语言描述
(4)线段树特点总结 利用线段树, 我们可以高效地询问和修改一个数列中某个区间的信息,并且 代码也不算特别复杂。 但是线段树也是有一定的局限性的, 其中最明显的就是数列中数的个数必须 固定,即不能添加或删除数列中的数。对于这个问题,下面介绍的伸展树就可以 完美的解决。
(7,10]
(0,1] (1,2] (2,3] (3,5] (5,6]
(6,7] (7,8]
(8,10]
(3,4]

线段树入门

线段树入门

线段树入门一、引言我们在做练习和比赛中,经常能碰见统计类型的题目。

题目通过输入数据给程序提供事物信息,并要求程序能比较高效地求出某些时刻,某种情况下,事物的状态是怎样的。

这类问题往往比较简单明了,也能十分容易地写出模拟程序。

但较大的数据规模使得模拟往往不能满足要求。

于是我们就要寻找更好的方法。

本文将介绍解决此类问题的一种方法——线段树。

二、线段树2.1 线段树的结构线段树是一棵二叉树,其结点是一条“线段”——[a,b],它的左儿子和右儿子分别是这条线段的左半段和右半段,即[a,[(a+b)/2]],[[(a+b)/2],b]线段树的叶子结点是长度为1的单位线段[a,a+1]。

下图就是一棵根为[1,10]的线段树:易证一棵以[a,b]为根的线段树结点数是2*(b-a)-1。

由于线段树是一棵平衡树,因此一棵以[a,b]为根结点的线段树的深度为log2(2*(b-a))。

线段树中的结点一般采取如下数据结构:其中a,b分别表示线段的左端点和右端点,Left,Right表示左儿子和右儿子的编号。

因此我们可以用一个一维数组来表示一棵线段树:Tree:array[1..Maxn] of TreeNode;a,b,Left,Right这4个域是描述一棵线段树所必须的4个量。

根据实际需要,我们可以增加其它的域,例如增加Cover域来计算该线段被覆盖的次数,bj域用来表示结点的修改标记(后面将会提到)等等。

2.2 线段树的建立我们可以用一个简单的过程建立一棵线段树。

Procedure MakeTree(a,b)Var Now:Longint;BeginInc(tot);Now:=tot;Tree[now].a:=a;Tree[now].b:=b;If a+1<b thenBeginTree[now].left:=tot+1;Maketree(a,(a+b)shr 1);Tree[now].right:=tot+1;Maketree((a+b)shr 1,b);End;End2.3 线段树中的线段插入和删除增加一个Cover的域来计算一条线段被覆盖的次数,即数据结构变为:因此在MakeTree的时候应顺便把Cover置0。

线段树ppt课件

线段树ppt课件


else Count := 0; 连接处颜色相同并且
非底色,则总数减1
统计算法
最左边的颜色
• end • else if r – l > 1 then
最右边的颜色
• begin
最左颜色=最右颜色=本身

result := Count(p * 2, l,非(底l +色则r)统d计iv数加2,1 lc, tl) +

else if a >= m then Insert(p * 2 + 1, m, r, a, b, c)

else begin

Insert(p * 2, l, m, a, m, c);

Insert(p * 2 + 1, m, r, m, b, c);

end;

end;
• end;
• end;
示例
• 初始情况 0 0 0 0 0
• [1,2]
10000
• [3,5]
10110
• [4,6]
10111
• [5,6]
10111
4个1
缺点
• 此方法的时间复杂度决定于下标范围的平 方。
• 当下标范围很大时([0,10000]),此方法 效率太低。
离散化的做法
• 基本思想:先把所有端点坐标从小到大排 序,将坐标值与其序号一一对应。这样便 可以将原先的坐标值转化为序号后,对其 应用前一种算法,再将最后结果转化回来 得解。
Wall
分析
• 这道题目是一个经典的模型。在这里,我 们略去某些处理的步骤,直接分析重点问 题,可以把题目抽象地描述如下:x轴上有 若干条线段,求线段覆盖的总长度。

线段树详解及例题

线段树详解及例题一、线段树的概念线段树(Segment Tree)是一种用于解决区间查询问题的数据结构,常用于静态区间查询和动态区间查询,也被称为区间树。

二、线段树的构建线段树是一棵二叉树,其每个节点都代表一个区间。

首先,我们将待处理的区间按照二叉树的方式进行划分,生成一棵满二叉树。

这里我们以求一段区间内元素的和为例:(1)首先,将整个区间 $[1,n]$ 分为两个部分,设左边区间为$[1,mid]$,右边区间为 $[mid+1,n]$。

这里的 $mid$ 是 $(1+n)/2$ 的值。

(2)然后,将左区间和右区间再分别划分成两个子区间并进行相加,直到区间大小为 1,构建出一棵完整的线段树。

三、线段树的维护构建好线段树之后,我们需要对其进行维护,以便能够快速地查询给定区间的值。

设线段树中某个节点代表区间 $[l,r]$,那么这个节点的值等于 $[l,r]$ 区间中所有元素的和。

如果需要对线段树进行更新,我们可以利用递归的方式向下更新每个节点的值。

当需要将 $[l,r]$ 区间中的某个元素修改为 $x$ 时,我们可以将其视为将线段树上区间 $[l,r]$ 的值都减去原来元素的值再加上 $x$。

四、线段树的查询线段树的查询包括单点查询和区间查询两种方式:(1)单点查询:即查询线段树中某个节点所代表的区间的值。

(2)区间查询:即查询线段树中 $[l,r]$ 区间内所有元素的和。

五、应用实例下面通过几道例题来说明线段树的应用。

问题一:给定一个序列,更新其中某个元素的值,并求出其区间和。

样例输入:8 1 3 -4 2 8 10 9 62 5 2样例输出:17问题二:对一个序列进行 $m$ 次操作,每次操作为在 $L$ 到 $R$ 的区间内加上 $c$,并输出最终改变后的序列。

样例输入:5 31 3 23 5 32 4 1样例输出:2 5 4 0 2以上就是关于线段树的详细介绍和几个应用示例,希望可以对读者有所帮助。

线段树专题题目

线段树专题题目:覆盖的面积(hdu -- 1255)Problem Description给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.Input输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.注意:本题的输入数据较多,推荐使用scanf读入数据.Output对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.Sample Input251 1 4 21 3 3 72 1.5 5 4.53.5 1.25 7.5 46 3 10 730 0 1 11 02 12 03 1Sample Output7.630.00Minimum Inversion Number(hdu-1394) The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:a1, a2, ..., an-1, an (where m = 0 - the initial seqence)a2, a3, ..., an, a1 (where m = 1)a3, a4, ..., an, a1, a2 (where m = 2)...an, a1, a2, ..., an-1 (where m = n-1)You are asked to write a program to find the minimum inversion number out of the above sequences.InputThe input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 ton-1.OutputFor each case, output the minimum inversion number on a single line.Sample Input101 3 6 9 0 8 5 7 4 2Sample Output16Tunnel Warfare(hdu -- 1540)Problem DescriptionDuring the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly connected with two neighboring ones.Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!InputThe first line of the input contains two positive integers n and m (n, m ≤ 50,000) indicating the number of villages and events. Each of the next m lines describes an event. There are three different events described in different format shown below:D x: The x-th village was destroyed.Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.R: The village destroyed last was rebuilt.OutputOutput the answer to each of the Ar my commanders‟ request in order on a separate line. Sample Input7 9D 3D 6D 5Q 4Q 5RQ 4RQ 4Sample Output124Atlantis(hdu--1542)InputThe input file consists of several test cases. Each test case starts with a line containing a single integer n (1<=n<=100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2(0<=x1<x2<=100000;0<=y1<y2<=100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area.The input file is terminated by a line containing a single 0. Don‟t process it.OutputFor each test case, your program should output one section. The first line of each section must be “Test case #k”, where k is the number of the test case (starting with 1). The second one must be “Total explored area: a”, where a is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point.Output a blank line after each test case.Sample Input210 10 20 2015 15 25 25.5Sample OutputTest case #1Total explored area: 180.00Just a Hook(hdu--1698)InputThe input consists of several test cases. The first line of the input is the number of the cases. There are no more than 10 cases.For each case, the first line contains an integer N, 1<=N<=100,000, which is the number of the sticks of Pudge‟s meat hook and the second line contains an integer Q, 0<=Q<=100,000, which is the number of the operations.Next Q lines, each line contains three integers X, Y, 1<=X<=Y<=N, Z, 1<=Z<=3, which defines an operation: change the sticks numbered from X to Y into the metal kind Z, where Z=1 represents the cupreous kind, Z=2 represents the silver kind and Z=3 represents the golden kind.OutputFor each case, print a number in a line representing the total value of the hook after the operations. Use the format in the example.Sample Input11021 5 25 9 3Sample OutputCase 1: The total value of the hook is 24.Luck and Love(hdu -- 1823)Problem Description由于人数太多,Wiskey实在忙不过来,就把统计的事情全交给了枫冰叶子,自己跑回家休息去了。

简单线段树知识点详解

简单线段树知识点详解简单线段树知识点详解本篇随笔讲解信息学奥林匹克竞赛中强⼤且常⽤的猛⼠数据结构——线段树。

因为线段树博⼤精深,有许多变形和应⽤⽅式。

区区⼀篇随笔是绝对⽆法尽叙的。

所以在这⾥笔者只为读者讲解简单线段树。

希望每⼀位有缘读到这篇随笔的⼈都能对线段树有⼀个深刻的理解,并会解决线段树的简单问题。

由于线段树属于⼀种⾼级数据结构。

所以在学习线段树的时候需要的知识铺垫⽐较多。

建议读者先对树状结构、⼆分以及递归编程法有深刻的认识和理解,然后再进⾏线段树的学习。

这样的话会⽅便很多。

当然,如果你缺少了前述铺垫知识的⼀项或⼏项,也并不代表你⼀定学不好线段树。

勇于尝试、敢于挑战、努⼒思考。

这会对你线段树及以后很多知识点的学习有极⼤的促进作⽤。

那我就开始了。

线段树的概念在介绍线段树的概念之前,我先介绍线段树的⽤途:线段树⼀般⽤于区间统计。

即统计[x,y]区间内的某⼀个特性。

这个特性可以有很多,⽐如区间求和,区间最值等等。

定义什么的特别复杂,我们争取⽤⼀张图搞清楚对线段树的直观理解。

上图是⼀棵1-5区间的线段树。

我们发现这个线段树是⼀棵⼆叉树,每个节点表⽰⼀个区间,根节点对应区间1-n.每个叶⼦节点都只表⽰单点,针对⼆叉树编号的性质(⼆叉树的每个⽗亲节点f的左节点编号是2f,右节点编号是2f+1),我们可以使⽤⼀维数组实现线段树。

也就是说,我们开⼀个⼀维数组,⼀维数组的下标表⽰这棵线段树的节点编号,⾥⾯存的值表⽰这个节点所表⽰的区间中我们要维护的特性:如和、最值等。

简单线段树⽀持的操作刚刚已经说过,线段树是⼀种博⼤精深的数据结构,它的功能和操作实在是太多了。

之所以反复强调这些,是为了让读者清楚,在线段树的海洋中,我们都不过是探其⼀⾓罢了,千万不要妄⾃尊⼤,以为⾃⼰已经把线段树全部搞完了。

简单线段树⽀持单点查询,区间查询,单点修改,区间修改,我们发现这和树状数组的⼀些⽀持项⽬类似,但是却不完全包含,因为树状数组仅⽀持区间求和,且必须是1−n的求和,如果想要[x,y]的任意区间求和的话,必须需要使⽤差分思想来相减。

线段树应用PPT课件


线段树与数组的比较
总结词
线段树在处理复杂查询时优 于数组
详细描述
数组虽然便于随机访问,但 在处理复杂查询如区间最大 值、最小值等问题时,线段 树能够提供更快的查询速度

总结词
线段树在处理动态数据集时更具优势
详细描述
当数据集频繁变动时,线段树能够快速地 更新和维护数据,而数组可能需要重新构 建或采取其他复杂的操作。
空间效率
线段树通过节点间的关系,将大 问题分解为小问题,所需空间相 对较小。
线段树的缺点
01
02
03
节点分裂与合并
在线段树进行插入、删除 等操作时,可能会导致节 点分裂或合并,使得树的 平衡性难以维护。
构造与重建
线段树在处理大规模数据 时,可能需要多次重建, 导致时间复杂度较高。
适用场景限制
线段树适用于区间查询问 题,对于其他类型的问题 可能需要其他数据结构或 算法。
线段树应用ppt课件
目录
• 引言 • 线段树的原理 • 线段树的应用实例 • 线段树与其他数据结构的比较 • 线段树的优缺点分析 • 总结与展望
01 引言
什么是线段树
定义
线段树是一种用于处理区间查询问题 的数据结构,它可以在线段上高效地 执行查询、更新和删除操作。
结构
线段树通常由一个根节点和若干个子 节点组成,每个节点包含一个区间的 信息,并且每个节点与其子节点之间 存在一一对应关系。
总结词
数组在随机访问和存储空间方面更具优势
详细描述
数组能够提供快速的随机访问,并且在相 同的数据量下,数组所需的存储空间可能 比线段树更少。
05 线段树的优缺点分析
线段树的优点
高效区间查询
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

线段树专题
1、PKU2352 star
2、校门外的树(tree)
0.2秒
在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,即每次种的树都不相同。

现有两个操作:
K=1,读入l,r表示在l~r之间种上的一种树
K=2,读入l,r表示询问l~r之间能见到多少种树
【输入文件】
第一行n,m表示道路总长为n,共有m个操作
接下来m行为m个操作。

【输出文件】
对于每个k=2输出一个答案
【样例】
tree.in tree.out
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
本题普及的试题数据很弱,但是时限缩短到原来的五分之一,那肯定要用线段树优化。

3、简单题(easy)
有一个n个元素的数组,每个元素初始均为0。

有m条指令,要么让其中一
段连续序列数字反转——0变1,1变0(操作1),要么询问某个元素的值(操
作2)。

例如当n=20时,10条指令如下:
操作回答操作后的数组
1 1 10 N/A 11111111110000000000
2 6 1 11111111110000000000
2 12 0 11111111110000000000
1 5 1
2 N/A 11110000001100000000
2 6 0 11110000001100000000
2 15 0 11110000001100000000
1 6 16 N/A 11110111110011110000
1 11 17 N/A 11110111111100001000
2 12 1 11110111111100001000
2 6 1 11110111111100001000
【输入文件】
输入文件easy.in第一行包含两个整数n,m,表示数组的长度和指令的条数,以下m行,每行的第一个数t表示操作的种类。

若t=1,则接下来有两个数L, R (L<=R),表示区间[L, R]的每个数均反转;若t=2,则接下来只有一个数I,表示
询问的下标。

【输出文件】
每个操作2输出一行(非0即1),表示每次操作2的回答。

【样例】
easy.in easy.out
20 10
1 1 10
2 6
2 12
1 5 12
2 6
2 15
1 6 16
1 11 17
2 12
2 6 1 0 0 0 1 1
【限制】
50%的数据满足:1<=n<=1,000,1<=m<=10,000 100%的数据满足:1<=n<=100,000,1<=m<=500,000
4、彩色穿孔卡片(punch)
问题描述
“在逃离诺莫瑞根的时候,我们留下了太多的数据!非常重要的数据!”大机械师卡斯派普十分着急地说,“尽管我们已经从矩阵打孔计算机上拿回了许多彩色穿孔卡片,但是混乱的数据令人无法忍受!”
自从诺莫瑞根陷落以后,侏儒们一直寄居在铁炉堡中。

大机械师卡斯派普花了不少钱来悬赏勇士们去诺莫瑞根替他取回一些卡片,现在他已经有了一大堆彩色穿孔卡片。

但是这些卡片都是残缺不全的,有的甚至还是无效的,想从这些破烂中恢复数据,实在是一件不容易的事。

卡斯派普发现每个卡片的开头和结尾都有标记,记录着它原本在矩阵打孔计算机中序列的位置,于是想出了一个恢复数据的方法。

把每张卡片看成数轴上的一条线段,开头和结尾的标记A,B为数轴上的两个点。

卡斯派普按拿到的顺序把卡片一张一张地贴到数轴上,每张卡片的颜色都不同。

他想知道贴完卡片以后的数轴上一共有多少种不同的颜色。

卡斯派普请你帮助他写一个程序来解决这个问题。

输入格式
第1行:一个整数N,表示卡斯派普收集到的卡片的数量。

第2行至第N+1行:第i+1行给出了第i张卡片的头尾两个标记Ai,Bi,贴卡片的顺序与输入文件中出现的先后顺序一致。

输出格式
一个整数,表示卡斯派普能在数轴上看到的不同的颜色的数目。

样例输入 punch.in
4
0 5
3 8
5 6
4 7
样例输出punch.out
3
样例说明
012345678
可以看到的不同颜色的卡片数为3,3号卡片被4号卡片所覆盖。

数据规模
50%的数据满足N<=1,000; 0<=Ai<Bi<=100,000(1<=i<=N);
100%的数据满足N<=20,000; 0<=Ai<Bi<=1,000,000,000(1<=i<=N)。

5、售票系统(RAILWAY)
问题描述:
某次列车途经C个城市,城市编号依次为1到C,列车上共有S个座位,铁路局规定售出的车票只能是坐票,即车上所有的旅客都有座位。

售票系统是由计算机执行的,每一个售票申请包含三个参数,分别用O、D、N表示,O为起始站,D为目的站,N为车票张数。

售票系统对该售票申请作出受理或不受理的决定,只有在从O到D的区段内列车上有N个或N个以上的空座位时该售票申请才被受理。

请你写一个程序,实现这个自动售票系统。

输入:
输入文件为:RAILWAY.IN,第一行包含三个用空格隔开的整数C、S和R,其中1<=c<=60000,1<=S<=60000,1<=R<=60000。

C为城市个数,S为列车上的座位数,R 为所有售票申请总数。

接下来的R行每行为一个售票申请,用三个由空格隔开的O、D和N 表示,O为起始站,D为目的站,N为车票站数,其中1<=D<=C,1<=O<=C,所有的售票按申请的时间从早到晚给出。

输出:
输出文件为:RAILWAY.OUT,共有R行,每行输出一个“YES”或“NO”,表示当前的售票申请被受理或不被受理。

样例输入:
4 6 4
1 4 2
1 3 2
2 4 3
1 2 3
样例输出:
YES
YSE
NO
NO
6、地平线(horizon)
在地平线上有n个建筑物。

每个建筑物在地平线上可以看成一个下边界和地
平线重合的矩形。

每个建筑物有三个描述(Li ,Ri,Hi),分别表示该建筑物的左边界,右边界,高度。

输出这些建筑物在地平线上投影的总面积。

【输入文件】
输入文件horizon.in第一行包含一个整数n,表示有n个建筑物。

以下n行,每行三个整数Li ,Ri,Hi。

【输出文件】
输出这些建筑物在地平线上投影的总面积
【样例】
horizon.in horizon.out 4
16
2 5 1
9 10 4
6 8 2
4 6 3
【限制】
100%的数据满足:1<=n<=40,000
1 ≤ Li < Ri≤ 1,000,000,000
1 ≤ Hi≤ 1,000,000,000。

相关文档
最新文档