专题集训--数据结构

来源:互联网 发布:python比较运算符 编辑:程序博客网 时间:2024/05/22 03:16

比赛链接:http://222.197.181.37/ContestProblems.aspx?ContestID=130

 

 

A :

题意:就是模拟你浏览器那种前进后退的过程。

做法:设置一个前进的栈,一个后退的栈,一个当前的页面。

然后按照题目中描述的VISIT , FORWARD BACK 三个的过程直接模拟就可以了哈。

 

B:

题意:给你两个表达式,问你这两个表达式是否是等价的。只有加减乘三种操作。

做法:用栈的方法去做。两个栈,一个数据栈,一个操作符栈。

每个操作符都是有优先级的‘(’ 的优先级最低,‘)’的优先级是最高的。

+ - 优先级小于*的优先级,然后字母的的值是直接用ASCII的值去代替。

然后从左往右去扫描,当当前的运算符优先级一直小于栈顶的优先级的时候,则取出栈顶运算符,和两个操作数,进行运算,然后把结果压入数据站,再把当前的运算符压入栈。保持运算符栈内的运算符的优先级是递增的皆可。

有个细微之处就是(的优先级压入栈后,优先级变为最低。遇到)的时候,一直取出运算符和操作数进行运算,直到(即可。

 

代码: 

 

 

C:

题意:给你n个数然后从左到右一个个的用长度为K的框去框K个数字,每次框住的最小和最大值。

解法:最大最小值都是一样的,所以只说求最小值的过程,最大值类似。

双队列扫描:保持队列里面是一个不降的序列即可。

从左到右的去扫描,每次先看队列尾的数是否比当前的数字大,如果一直大,则一直从队尾出元素。一直出到队尾元素不大于当前元素。然后把当前的元素压入队尾。然后考察队列头,如果队列头的元素的位置离当前的位置大于K的话,则从队头出元素,一直出到不大于K。

然后队头元素就是要求的那个值了的。

代码:

 

 

D: 

题意:出现SARS,N个人,0号人是SARS确诊病例,然后有一些关系,表示N个人之间的关系。只要存在关系的人中有一个是和SARS患者接触都认为疑似病例,就是和0号人接触的。最后问你有多少个意思病例,包括0号人。

做法:很简单,就是个简单的并查集。有个小地方,就是0号人和其他人关系的时候,合并的时候一定把其他人指向0号。就是0号人一直做一个集合的代表元素。最后统计所有的元素中,他所在集合的代表元素是0的个数。

 

E:

题意:给你n*n的一个地图吧。然后每个点有个淹没时间,现在给你一些时间点,问你这些时间点的时候,有多少个连通块是没有被水淹没的。

解法:其实正着写没有思路的。于是倒着去想,想水退去的过程,有多少露出水面的。。

于是把所有的格子按照被淹没时间从大到小去排序。然后按照时间点从后往前去做。

每次如果格子淹没时间大于询问时间点,则进行处理。询问他周围的四个点是否是被淹没的。分别属于那个集合的,然后记录这四个集合的集合代表元素,被淹没的记作-1。如果这四个都是-1的话就res++;如果有两个有不同的就证明你合并了两个连通块,则res--;然后把周围的四个的集合代表元素设置为当前的这个点。如此做即可。

代码: 

 

F:

题意:就是给你n个数字,问你每次去两个数字求和。然后把和值加入其中,依次进行直到只剩下一个数字,问这些次每次的求的和值最小。

就是个简单的霍夫曼树的模型。

解法:每次取出最小的两个元素,把结果丢进去继续。直到只剩下一个元素即可。

做法:1:优先队列STL,2:手写堆去做。

 

G:

题意:动态的对一个集合加入值删除值,问你这个集合中的一些数的性质,比如第k大的是多少,比C小的rank最大的最小的分别是好多。

解法:因为数值范围过大,所以要离散化。

然后二分+树状数组可以做,用平衡树去做也可以去做的。

1:rank 为K的。二分一个值,然后去用树状数组去验证就可以了的。

2:C的rank就是直接树状数组中值

3 ,4 比C的rank值大的或者小的D分别为多少.也是一个二分加树状数组验证,只是需要注意处理方法,其实只要二分的时候加上一个res记录有效值就很容易的避免了二分写错的情况。

 

H:

题意:给你n根棍子,初始的时候起每根价值为1,然后可以动态的更新一段区间的棍子的单价,然后动态询问n根棍子的价值

解法:线段树去写。记录域:1:记录当前区间的总价值。2:记录当前区间是否被修改过。

然后用懒操作去做。最后的结果在线段树的根的域上。

 

代码: 

 

I

题意:给你一些二维空间的星星,每个星星的rank值为x值不大于并且y值不大于的星星个数。

然后把每个rank值的星星个数输出。

解法:因为输入是有序的,所以直接按照给的顺序去树状数组去做就好了。没啥需要注意的,树状数组很强大的说。。。

 

J

题意:给你n个数字,然后可以动态的对一个区间加一个值,然后动态的询问某个区间的和。

解法:又是线段树。记录域:1:这个区间的和,2:这个区间额更改值。

懒操作直接用第二个记录域即可的。所以很容易去做的。和H类似。

 

K

题意:长度为L的黑板,然后可以动态的在一段区间图上某种颜色,然后动态的询问一段区间的有多少不同的颜色

解法:这题继续线段树。只是用个小技巧,因为颜色种类不多,所以用个Int二进制位去记录这个区间上某种颜色是否存在。

1:int二进制位记录颜色是否存在。2:区间是否被修改。

然后就线段树去做了。当前区间等于两个子区间的或值。

 

L

楼爷的题,果断膜拜之。。。

题意:给你一个矩阵。每个格子有个状态,0 或者1 ,然后可以动态的改变某个子矩阵的所有格子的状态。最后动态的问你某个格子的状态。

解法:二维的树状数组。记录当前有多少次被改变。更新某个子矩阵的时候,

  •    updata(x1,y1,1 );   
  •                 updata(x2+1,y1,-1);   
  •                 updata(x1,y2+1,-1);   
  •                 updata(x2+1,y2+1,1);   
  •  画个简单的图就可以理解了的。

    然后询问的时候直接就是二维树状数组求和的值。

     

    题意:给你N个矩形,这些矩形可能重叠。然后问你所组成形状的周长。

    解法:先扫描+线段树记录

    先对于每个矩形保存四条边。分别2条加入边,2条离开边。

    然后分别对x方向y方向去扫描。x方向扫,对Y建颗线段树,Y方向扫,对X方向建线段树。

    线段树记录的是当前区间被覆盖多少次,当覆盖的次数大于0 ,res域为当前区间的长度,为0,res为0 。

    然后每次加入(删除)边前询问根节点的res域,加入(删除)边后询问根节点的值,然后两者差值即为当前这条边所影响的周长的长度。把所有的边处理完了就是结果了的。

     

    代码: 

    注释部分是另一种处理方法,只是比较烦而已。

     

    N

    题意:就是有N个房间,现在动态的有旅行团来入住,他们需求一段连续的K个房间,要分配给他最靠前的连续的K个房间,不存在就不分配,输出0,不然输出最前的那个房间号。还有个操作就是离开操作,使得某个区间的房间空出来。

     

    解法:线段树:

    记录域:1:当前区间左端点开始往后最大的空房间的长度,Llen。

                2:当前区间右端点开始往前最大的空房间的长度, Rlen

        3:当前区间最长的一段空房间的长度。Mlen

         4:有个标记域,记录当前区间是否有入住或者退房的操作。

     

  •  if( tree[p*2].Llen  == tree[p*2].qlen )tree[p].Llen = tree[p*2].qlen + tree[p*2+1].Llen ;   
  •     else tree[p].Llen = tree[p*2].Llen ;    
  •   
  •     if( tree[p*2+1].Rlen  == tree[p*2+1].qlen )tree[p].Rlen = tree[p*2+1].qlen + tree[p*2].Rlen ;   
  •     else tree[p].Rlen = tree[p*2+1].Rlen ;   
  •   
  •     tree[p].Mlen = max( tree[p*2].Mlen , max( tree[p*2+1].Mlen , tree[p*2].Rlen + tree[p*2+1].Llen ) ) ;    
  •  

    这样子去更新每个域。询问的时候就很简单了。如果当前区间Llen大于需求,则返回左端点。

    不然如果如果左儿子的最大空大于需求,则递归到左儿子,不然如果左儿子Rlen+右儿子Llen大于需求则返回左儿子右端点往前走Rlen。

    不然如果右儿子最大域大于当前需求,则递归右儿子,不然返回0。

     

    代码:

     

     

     

    还有很多其他的数据结构得去慢慢学。

     

    数据结构:

    链表,队列,栈,及其变形

    堆,平衡树。

    树状数组,线段树。

    等等很多。慢慢学习,一步步总结,会后续放上。

    接下来一步步切

    http://www.notonlysuccess.com/?p=59

    线段树总结,然后再来总结线段树,一步步来吧。

     

    原创粉丝点击