随笔分类 -  DS——线段树&&数状数组

摘要:题意:求[l, r]区间内不重复的数的和。N个数,M次询问解:离线处理M次询问,看得别人的思路后才知道的。。。思维局限在预处理N个数上了。。。对M次询问按右区间的值从小到大排序。扫一遍N个数,如果发现当前这个数在之前出现过,就从之前出现这个数的位置上把这个数删除,在新位置上插入这个数。这样做的好处是删除前面重复的不会影响后面的。时间复杂度控制在(N + M)logN的数量级上。ps:午不眠,困乎,我命休矣。#include <iostream>#include <cstdio>#include <cmath>#include <vector>#i 阅读全文
posted @ 2013-06-05 13:58 AC_Von 阅读(276) 评论(0) 推荐(0) 编辑
摘要:Stack is one of the most fundamental data structures, which is based on the principle of Last In First Out (LIFO). The basic operations include Push (inserting an element onto the top position) and Pop (deleting the top element). Now you are supposed to implement a stack with an extra operation: Pee 阅读全文
posted @ 2013-03-27 18:50 AC_Von 阅读(780) 评论(0) 推荐(0) 编辑
摘要:题意:给一个长度为N(N < 50000)的序列,求这个序列中长度为5的递增子序列的个数。思路:对于长度为5的子序列,先考虑长度为1的子序列,第i个位置以i结尾长度为1的子序列个数为1。第i个位置以i结尾长度为2的子序列个数为i之前并且小于a[i]的长度为1的子序列的个数。同理,第i位置长度为3的子序列个数为i之前小于a[i]的长度为2的子序列的个数。。。依次往后推。比如原序列为:(1, 2, 4, 6, 3) 推: -> (1, 1, 1, 1, 1)1 -> (0, 1, 2, 3, 2)2 -> (0, 0, 1, 3, 1)3 -> (0, 0, 0, 1 阅读全文
posted @ 2013-01-18 16:52 AC_Von 阅读(945) 评论(0) 推荐(0) 编辑
摘要:感觉树状数组要比线段树优雅。。。反素数打表什么的都搞好了,就是从当前位置推下一个位置的公式没搞出来,后来看得别人的。。。if(p[now].x > 0) nxt = (nxt - 1 + p[now].x)%leave;else nxt = ((nxt + p[now].x)%leave + leave)%leave;然后在树状数组里找第nxt大的数(二分)。。。View Code //#pragma comment(linker,"/STACK:327680000,327680000")#include <iostream>#include <cs 阅读全文
posted @ 2012-10-28 09:50 AC_Von 阅读(567) 评论(0) 推荐(0) 编辑
摘要:这神题,暴力数组可过,vector可过,线段树可过。。。时限拉的太长了,所以就成水题了。。。不过比赛的时候真的没敢用数组暴力写。。。说说线段树的思路吧。对树的每个节点 L, R, cnt, sum[5],分别表示左区间,右区间,这段区间上的点数,这段区间上sum[x%5]的和。先把所有的数据都读入,然后离散化,去掉重复的数据建树。再处理一边就可以了。ps:叶节点只有sum[0]需要更新,sum[1...4]更新不到。。这个注意理解。。View Code #include <iostream>#include <cstdio>#include <cmath># 阅读全文
posted @ 2012-09-18 20:43 AC_Von 阅读(352) 评论(1) 推荐(0) 编辑
摘要:这个题好纠结。。。比赛没思路,回头又看得出题报告。最后写出来的数状数组跑了1.5s。。。数状数组的思想还算好理解,就是对角线的控制上。。纠结了。一个直观的想法是首先用N^2的时间预处理出每一个是1的点向上下左右四个方向能够延伸的1的最大长度,记为四个数组l, r, u, d。然后我们观察到正方形有一个特征是同一对角线上的两个顶点在原方阵的同一条对角线上。于是我们可以想到枚举原来方阵的每条对角线,然后我们对于每条对角线枚举对角线上所有是1的点i,那么我们可以发现可能和i构成正方形的点应该在该对角线的 [i, i + min(r[i], d[i]) – 1] 闭区间内, 而在这个区间内的点 j 只 阅读全文
posted @ 2012-08-05 21:39 AC_Von 阅读(251) 评论(0) 推荐(0) 编辑
摘要:/*在求周长之前最好线看一下求面积,这样再求周长回好理解很多。题目是POJ 1177http://poj.org/problem?id=1177POJ 1151也是这类问题,不过是求面积的,更简单一些。*/#include <iostream>#include <cstdio>#include <cmath>#include <vector>#include <cstring>#include <algorithm>#include <string>#include <set>#include &l 阅读全文
posted @ 2012-06-25 10:35 AC_Von 阅读(745) 评论(0) 推荐(0) 编辑
摘要:转载自:http://hi.baidu.com/diannaochina/blog/item/48dfff33c3c36840ad4b5fb5.html一、最近公共祖先(Least Common Ancestors)对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。另一种理解方式是把T理解为一个无向无环图,而LCA(T,u,v)即u到v的最短路上深度最小的点。这里给出一个LCA的例子:例一对于T=<V,E>V={1,2,3,4,5}E={(1,2),(1,3),(3,4),(3,5)}则有:LCA(T,5,2)=1 阅读全文
posted @ 2012-05-03 19:15 AC_Von 阅读(587) 评论(0) 推荐(0) 编辑
摘要:二维树状数组用来更新矩阵,写法跟一维的很类似。每次增加i&(-i)的值,不过这里增加的是矩阵的横纵下标;写法如下:void add(int x, int y, int d) { int i, j; for(i = x; i < N; i += lowbit(i)) for(j = y; j < N; j += lowbit(j)) mat[i][j] += d;}LL sum(int x, int y) { LL res = 0; int i, j; for(i = x; i > 0; i -= lowbit(i)) ... 阅读全文
posted @ 2012-04-30 23:00 AC_Von 阅读(2054) 评论(0) 推荐(1) 编辑
摘要:数据结构线段树poj2528,poj2828,poj2777,poj2886,poj2750, poj2892(区间更新)静态二叉检索树,平衡树treap,splaypoj2482, poj3468树状树组poj1195,poj3321, poj2352RMQpoj3264,poj3368并查集的高级应用poj1703, poj2492KMP算法poj1961,poj2406 线段树poj 2528以前做过多次,思路很明显,线段数分区间染色,最后统计颜色的个数。我犯了一个极度二百五的错误,导致这题提交5次!!!col的初始化是-1,更新时我当成0了。T_TView Code #inclu... 阅读全文
posted @ 2012-04-29 13:33 AC_Von 阅读(955) 评论(0) 推荐(0) 编辑
摘要:/*额滴神啊。。。调了整整一晚上。简单染色问题,染完色后再扫描一遍,找出最大的连续是白色的序列。开始必须把0, 109 这两个点加上去。就因为这个都快调shi了。。。扫描的时候用一个数组记录染色后区间的颜色。然后找连续颜色是白色的最大区间。数据有点大,用离散化吧。*///My Code:#include <iostream>#include <cstring>#include <cmath>#include <cstdio>#include <map>#include <queue>#include <stack&g 阅读全文
posted @ 2011-12-01 22:10 AC_Von 阅读(250) 评论(0) 推荐(0) 编辑
摘要:/*开始没看懂题意。悲剧了一晚上。。。题意是N个人编号,1号最高,N号最矮,从后往前跳。我看成1号最矮,N号最高了。其实可以把输入的数转化一下,让1号最矮,N号最高,这样就好处理了。*///My Code:#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N = 10007;int c[N], n;int lowbit(int i) { return i&(-i);}void add(int i, int val) { while(i 阅读全文
posted @ 2011-12-01 15:21 AC_Von 阅读(309) 评论(0) 推荐(0) 编辑
摘要:以前在poj做过,今天有做了下,TLE了。看了一下原来的代码,原来忘了输入的横坐标可能是0的情况了。做下笔记:int lowbit(int i) { return i&(-i);}void add(int i, int val) { //加元素 while(i <= N) { c[i] += val; i += lowbit(i); **i不能是0,否则死循环** }}int sum(int i) { //求和 int s = 0; while(i > 0) { s += c[i]; i -=... 阅读全文
posted @ 2011-11-19 12:58 AC_Von 阅读(260) 评论(0) 推荐(0) 编辑
摘要:/*线段树扫描线问题,感觉可以作为这类问题的模板。问过师兄以后才过的。。。按y轴建线段树。*/struct node{ int l, r, c; //c表示被覆盖的情况,不为0表示被覆盖 double sum, len; //len表示当前段的长度,sum表示有效长度。就是可以计入求面积的长度}node[N<<2];struct line{ double x; //记录x坐标 double y1; double y2; //y1,y2用来记录平行y轴的线段的两个端点, int flag; //标记是左边的边还是右边的边}l... 阅读全文
posted @ 2011-10-26 15:11 AC_Von 阅读(285) 评论(0) 推荐(0) 编辑
摘要:话说这题从我开始学线段树就开始做,直到今天才A掉,前后有近3个月吧。今天重新翻这个题,思路有点乱,看了一下大牛的代码。然后就自己写,没想到,居然敲了一遍就过了,激动啊~~3667Accepted3200K625MSC++2422B2011-10-25 17:50:22思路: 结构体定义包含:l, r, cov, ls, sum, rs。其中:ls表示从左边数连续的空余空间大小,rs表示从右边数连续的空余空间大小。sum表示整段上最大的空余空间大小。查询时。当查询到当段段的sum > len时,满足条件。更新时,当cov改变,同时要改变当前段的ls、rs、sum。当一段更新完后还要上传co 阅读全文
posted @ 2011-10-25 18:47 AC_Von 阅读(247) 评论(0) 推荐(0) 编辑
摘要:这题纠结了两天,开始一点思路没有,后来看到有大牛把这题的做法称作区间树,并说明了区间树与线段树的区别(区间树是区间内被染色的区间标记为1,未被染色的区间标记为0)。我觉得这就是线段树的一类操作,没有必要分出去吧。。。思路:区间更新,首先想到的应该是Lazy思想;这题分五种情况:CommandSemanticsUTS←S∪TITS←S∩TDTS←S−TCTS←T−SSTS←S⊕TU:直接将T对应的区间覆盖为1;I:将T的补区间(比如T[l, r], 补区间就是[0, l-1], [r+1, N])清零即可;D:直接将T区间清零;C:先将T的补区间清零,再对T区间取反;S:直接对T区间取反;(.. 阅读全文
posted @ 2011-09-20 22:13 AC_Von 阅读(314) 评论(0) 推荐(0) 编辑
摘要:/*第二次做这题,其中有些坎坷,第一次做时理解的也不深刻,导致这次做起来有些费劲。开始思路是一边更新一边计算总的Hook值,可惜一直WA,做了大半下午,晕死,先更新完再统计一遍的方法过了,再后来上网查了一下,正好有个大牛也是用第一种思路做的,参考了一下他的代码,发现原来我的flag初值整错了。。。。*///第一种思路代码(609+ms):#include <iostream>#include <cstdio>#define L(t) t << 1#define R(t) t << 1 | 1using namespace std;const in 阅读全文
posted @ 2011-09-16 16:20 AC_Von 阅读(219) 评论(0) 推荐(0) 编辑
摘要:/*题意:输出每次贴上的海报所在的行号,行号为1...h;开始拿到这题没思路,后来问了问本校的大牛,终于找到思路。这题是按high建树,结构体中定义一个len变量,存放当前该结点的空闲长度。某结点的父结点存放其子结点的最大空闲长度值;比如(len = 10): 1 len = max(len2,len3) / \ 2 3 (len = max... 阅读全文
posted @ 2011-09-15 21:52 AC_Von 阅读(231) 评论(0) 推荐(0) 编辑
摘要:/*设原序列的逆序数为sum,每往后移一个数,可以找到规律sum += n-2*num[i]-1;(n为元素个数,num[i]为移动的数);求原序列的逆序数时可以用线段树,每输入一个数,先querry [输入的数,n]中元素的个数,再把num[i]插入到线段树中。。。*/#include <iostream>#include <cstdio>#include <cstring>#define L(x) x << 1#define R(x) x << 1 | 1using namespace std;const int N = 5005 阅读全文
posted @ 2011-09-14 21:25 AC_Von 阅读(164) 评论(0) 推荐(0) 编辑
摘要:结构体中定义记录染色次数的参数(cov),更新时直接找到对应的区间,使cov++。查询时要有点小操作。查询过程:void query(当前节点 t,要查询的点 x){ if(找到要查询的点) return cov; if(该点的cov > 0) { 左孩子.cov += 当前节点.cov; 右孩子.cov += 当前节点.cov; 当前节点.cov = 0; } mid = (左孩子+右孩子) >> 1; if(x <= mid) query(左孩子, x); else query(右孩子, x);}下边是完整的代码:View Code #include <std 阅读全文
posted @ 2011-08-15 17:27 AC_Von 阅读(214) 评论(0) 推荐(0) 编辑

点击右上角即可分享
微信分享提示