随笔分类 - 树状数组-线段树
摘要:给出一段序列,要求任意区间内最大连续和所在的区间,首先肯定是要用线段树去解决,并不是要求直接输出和,这样一来就要麻烦一点,如果不要求输出下标,那么一段区间的最大连续和可能来自三部分,左半部分的最大连续和,右半部分的最大连续和,左半部分从最右端开始的和的最大值和右半部分从最左端开始的和的最大值的和,所以,需要每个节点需要记录本节点的最大连续和,左端开始的最大连续和,右端开始的最大连续和,而要得到父节点的左端开始的最大连续和,还需要子节点整个区间的和,所以还要记录节点整个区间的和,现在要求输出下标,那么就要记录每一个和的起始位置,在合并选择的时候就可以直接得到了,所以一个节点需要记录10项,合并的
阅读全文
摘要:又一道矩形面积并,只要要统计七种颜色分别的面积,所以在线段树里维护一个颜色数组,一个各种颜色覆盖长度的数组,其余的和求矩形面积并就很类似了View Code 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #define N 10005 6 #define L(x) (x<<1) 7 #define R(x) (x<<1|1) 8 using namespace std; 9 typedef long l
阅读全文
摘要:周长并和面积并的代码基本上差不多,只不过多了两个rb,lb判定端点是否被覆盖的判断,维护的过程也增加了一点难度,但是整体上是差不多的。View Code #include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include <algorithm>#define N 5005#define L(x) x<<1#define R(x) x<<1|1using namespace std;struct node{ int l,r,nu
阅读全文
摘要:线段树题目,给出一个序列,查询一段a,b之间的最大的连续相同的数字的和最大是多少,定义为MS,因为对于一个区间的MS,可能来自于左子节点或者右子节点,或者当左节点最右面的数字和右节点的左面的数字相同时可能会来自两个节点合并的部分,所以,树中的节点要维护五个基本的值,lval(最左侧的值),lnum(最左侧值连续的个数),rval(最右侧的值),rnum(最右侧值连续的个数)以及MS,为了提高效率,还要增加一个标记值,不需要更新每一个节点。View Code #include<iostream>#include<cstdio>#include<cstring>
阅读全文
摘要:二维树状数组:类似于一维的状态下,二维存储的是一个区域内的状态。View Code 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define N 105 5 #define lowbit(x) x&-x 6 using namespace std; 7 int f[N][N]; 8 void init() 9 {10 memset(f,0,sizeof(f));11 }12 int m,n;13 void add(int x,int y,int v)14 {15 int
阅读全文
摘要:这个可以作为线段树的模板来使用了,很经典,以前总是搞不清楚要向下更新,这次是明白了,多次修改很多区间时没必要每次都去修改,可以最后一块修改View Code 1 #include<stdio.h> 2 #include<string.h> 3 #define N 100005 4 struct node 5 { 6 int r,l; 7 long long sum,v; 8 }; 9 node p[4*N]; 10 long long val[N]; 11 void build(int l,int r,int i) 12 { 13 p[i].r=r;...
阅读全文
摘要:链接:http://poj.org/problem?id=1151线段树的经典应用,求矩形的面积并,把点的位置离散化,看着别人的代码打出来的,还是没怎么搞懂,看来还是要好好研究研究才好啊,线段树用起来真的太灵活,真的要多练习才好啊。View Code 1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #define l(x) x<<1 5 #define r(x) x<<1|1 6 double y[1000]; 7 struct Line 8 { 9 do
阅读全文
摘要:链接:http://poj.org/problem?id=3321树状数组的题,只是要注意把深搜的时间戳当作是数组的下标,而且如果是根节点,为保证唯一性,结束时间和开始时间应该是一个值,而非根节点的结束时间应为所有根节点结束时间的最晚的View Code 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define lowbit(x) (x)&(-x) 5 #define N 100005 6 using namespace std; 7 int d[N],f[N],tim
阅读全文
摘要:链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1390这道题,真的挺厉害,虽然用到的东西都不难,但是考察了很多方面,树状数组和二分,这个全用到了,并且还要记录是否访问过View Code 1 #include<stdio.h> 2 #include<string.h> 3 #define N 100005 4 int a[N]; 5 int used[N]; 6 int n; 7 int lowbit(int x) 8 { 9 return x&am
阅读全文
摘要:链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1250这道题是求最小逆序数的题,用树状数组和线段树都可以解决,其实最耗费时间的是求原序列的逆序数的部分View Code 1 #include<stdio.h> 2 #include<string.h> 3 #define N 5005 4 int a[N]; 5 int v[N]; 6 int n; 7 int lowbit(int x) 8 { 9 return x&-x;10 }11 in
阅读全文
摘要:链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1189这道题是用线段树去求区间最大值的一道题,树状数组对于这个数据量已经显得无能为力了,这也说明了树状数组和线段树分别适合的不同的题View Code 1 #include<stdio.h> 2 #include<string.h> 3 #define N 100005 4 int max(int a,int b) 5 { 6 return a>b?a:b; 7 } 8 int n; 9 stru
阅读全文
摘要:链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1360这道题的题意是说,一个图中的点相互连接,但是不同的城市之间的连线的警戒等级是不一样的,由低到高分为a,b,c三级,两个点之间可能有多条路径连接,每条单独的路径的警戒级别是这条路径上的警戒级别最高的那条路的级别,而两个城市之间的警戒级别是所有路径当中警戒级别最低级别,这是一道比较难的并查集的问题,关键就在于是什么时候该用哪一个级别的合并函数将两个点合并,很明显如果a,b两点之间有一条级别为a的路相连,那么b和所有与a相连的
阅读全文
摘要:poj 3264-Balanced Lineup链接:http://poj.org/problem?id=3264题意说明:有n个数,要求随时统计一定区间上最大值和最小值的差从题意也能看出来是线段树的问题,节点在建立的时候包括区间的最大值与最小值。View Code 1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 using namespace std; 5 #define N 400005 6 int min(int a,int b) 7 { 8 return a<b?a
阅读全文
摘要:poj 2777-Count Color链接:http://poj.org/problem?id=2777题意是说有一段长为lcm的线段,每段的长度为1cm总共有t种颜色可以用来给它涂色,我们会随时改变某个区间的颜色,并且询问这个区间内共有多少种不同的颜色典型的线段树问题,这其实也体现出了线段树比树状数组比起来的优势,所能统计的信息比树状数组要多,用起来更加灵活。View Code 1 #include<stdio.h> 2 #include<string.h> 3 #define MAX 450000 4 struct node 5 { 6 int l,r; 7 in
阅读全文

浙公网安备 33010602011771号