线段树

hdu2795(线段树)

妖精的绣舞 提交于 2020-01-05 03:29:18
http://acm.hdu.edu.cn/showproblem.php?pid=2795 题意:有一块尺寸为h*w的矩形长板,要在上面贴1*wi的海报n张,选择贴海报的位置是:尽量高,同一高度,选择尽量靠左的地方。要求输出每张海报的高度位置。 思路:用线段树来做。在结构体中有一个num变量,装每段区间剩余的最大长度,然后与输入进来的长度len比较,根据题意应该先是左边比较,再是右边比较。还有,就是最多只有200000个点,但是要是高小于200000,那么就应该用高来建树,因为200000个点,其高度最多为200000....... 反思:此题用线段树来做的最大好处是,它是用最底层的单个结点(也就是当tree[i].l==tree[i].r时的点)来表示高度的.......只要理解这里,这个题目就是水题了,同样的,要是不理解,它就是“难题”。好吧,总结一句,其实还是自己太水...... #include<iostream> using namespace std; #define N 200005 int h,w,n; struct { int l,r; int num; }tree[N*4]; int maxn(int h,int n) { if(h>n) return n; else return h; } int maxx(int a,int b) { if(a>b)

hdu 4046 Panda 线段树

亡梦爱人 提交于 2020-01-05 03:26:26
五场的网络赛的题目出现了大量的线段树的题目,每次都只能坐在那里干瞪眼。。 看来需要好好的啃啃线段树了。。 #include<iostream> #include<string> #define maxn 50010 #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 using namespace std; int sum[maxn*4]; char str[maxn]; int a[maxn]; void PushUP(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void build(int l,int r,int rt) { if (l == r) { sum[rt]=a[l]; return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUP(rt); } void update(int p,int add,int l,int r,int rt) { if (l == r) { sum[rt] = add; return ; } int m = (l + r) >> 1; if (p <= m) update(p , add , lson); else update(p ,

hdu4553约会安排 线段树

天涯浪子 提交于 2020-01-05 03:25:37
//DS QT 找一段最靠前的长度为QT的空间 //NS QT 找一段最靠前的长度为QT的空间。假设没找到能够将DS占领的空间当做空暇空间,找一段最靠前的空间 //STUDY!! L R 清空L ,R的空间 //用两个线段树,一个处理DS的情况。一个处理NS的情况 //线段树维护,ma_l , ma_r , ma 区间[l,r]的左边的空暇区间,右边的以及最大的空暇区间 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std ; const int maxn = 1e5 + 10; #define left v<<1 #define right v<<1|1 struct node { int l , r ; int ma_l ; int ma_r ; int ma ; int lazy ; }tree[2][maxn<<2] ; void build(int l , int r , int v) { for(int i = 0;i < 2;i++) { tree[i][v].l = l ; tree[i][v].r = r; tree[i][v].lazy = -1; tree[i][v].ma_l = tree[i][v].ma = tree[i]

POJ 2155 Matrix【二维线段树】

£可爱£侵袭症+ 提交于 2020-01-05 03:24:36
题目大意:给你一个全是0的N*N矩阵,每次有两种操作:1将矩阵中一个子矩阵置反,2.查询某个点是0还是1 思路:裸的二维线段树 #include<iostream> #include<cstdio> #include <math.h> #include<algorithm> #include<string.h> #include<queue> #define MOD 1000003 #define maxn 4009 #define LL long long using namespace std; int n,num; bool tree[maxn][maxn]; void add_y(int xx,int node,int l,int r,int ql,int qr) { if(ql<=l && r<=qr){tree[xx][node]^=1;return ;} int mid=(l+r)>>1; if(ql<mid)add_y(xx,node*2,l,mid,ql,qr); if(qr>mid)add_y(xx,node*2+1,mid,r,ql,qr); } void add_x(int node,int l,int r,int ql,int qr,int y1,int y2) { if(ql<=l && r<=qr){add_y(node,1,1,n+1,y1,y2)

UVA 11297 Census(二维线段树)

别等时光非礼了梦想. 提交于 2020-01-05 03:24:13
Description This year, there have been many problems with population calculations, since in some cities, there are many emigrants, or the population growth is very high. Every year the ACM (for Association for Counting Members) conducts a census in each region. The country is divided into N^2 regions, consisting of an N x N grid of regions. Your task is to find the least, and the greatest population in some set of regions. Since in a single year there is no significant change in the populations, the ACM modifies the population counts by some number of inhabitants. The Input In the first line

POJ2029 二维线段树

青春壹個敷衍的年華 提交于 2020-01-05 03:23:49
Get Many Persimmon Trees POJ - 2029 Seiji Hayashi had been a professor of the Nisshinkan Samurai School in the domain of Aizu for a long time in the 18th century. In order to reward him for his meritorious career in education, Katanobu Matsudaira, the lord of the domain of Aizu, had decided to grant him a rectangular estate within a large field in the Aizu Basin. Although the size (width and height) of the estate was strictly specified by the lord, he was allowed to choose any location for the estate in the field. Inside the field which had also a rectangular shape, many Japanese persimmon

[hdu-6638]Snowy Smile 线段树维护 带修改的区间最大字段和 最大子矩阵 2019多校6

被刻印的时光 ゝ 提交于 2020-01-05 03:23:36
链接: acm.hdu.edu.cn/showproblem.php?pid=6638 题目大意:给n个点 的坐标和权值,画一个矩形(边平行于坐标轴),矩形的值为矩形内部和边界所有点的和,求最大的矩形的值。 题解:求最大的子矩阵和 因为点的坐标x,y范围太大,先离散,变为1~2000内的数 把x放到数组里排序去重,二分查找下标(y相同) 先说一开始想的几个TLE的方法 1.直接二维差分 维护二维前缀和 ,暴力枚举每一个矩形 O(N^4) 2.dp O(N^3) 求最大字段和的方法 dp[i]为以i为结尾的最大的字段和 dp[i]=max (dp[i-1]+a[i],a[i]); 二维的最大子矩阵的方法: 我们先维护每一列的前缀和 枚举矩形上下边界l,r,我可以O(1)求出l-r区间内每一列i的和y,直接差分 y=sum[r][i]-sum[l-1][i]; 神奇的事发生了,每一列被压缩成了一个数,又变为了求最大字段和 3.正解:O(N^2 log(N)) 我们在上一个方法枚举上下边界l,r 后,变为求这个上下边界的最大字段和; 在移动了一行下边界后,我们把新加入的一行的新点修改———带修改的最大字段和(我们可以用线段树来维护最大字段和)。 把n个点按横坐标排序,从前往后加入,就按行加入了。 线段树维护: lm 左端点开始的最大字段和 rm 右端点开始的最大字段和 sm

[BZOJ4184]shallot 线段树+线性基

假如想象 提交于 2020-01-05 03:19:44
链接 题意:给你每个数字出现的时间和消失的时间,求每个时刻最大异或和 题解 按照时间建立线段树,线段树每个节点开个vector存一下这个时间区间有哪些数,然后递归进入的时候加入线性基,开一个栈记录一下加了哪些基底,回溯的时候把之前加的删掉即可 #include<bits/stdc++.h> #define REP(i,a,b) for(int i(a);i<=(b);++i) using namespace std; typedef long long ll; inline int read(){char c,p=0;int w; while(!isdigit(c=getchar()))if(c=='-')p=1;w=c&15; while(isdigit(c=getchar()))w=w*10+(c&15);return p?-w:w; } inline char smax(int&x,const int&y){return x<y?x=y,1:0;} inline char smin(int&x,const int&y){return x>y?x=y,1:0;} const int N=5e5+5,n=read(); vector<int>g[N<<2]; #define ls o<<1 #define rs o<<1|1 inline void ins(int o,int l

hdu3911 线段树的区间更新

╄→尐↘猪︶ㄣ 提交于 2020-01-05 03:18:18
  题目链接如下:http://acm.hdu.edu.cn/showproblem.php?pid=3911 大意是给你一个01串, 以及两种操作, 第一种操作是询问区间内连续的1的个数, 第二种操作是翻转一个区间内的0 和 1, 我们直接在维护一个区间左端开始连续的0 和 1的个数, 右端开始连续的0 和 1的个数, 以及当前区间连续的1 和 0的最大数量, 即可 , 在pushup更新的时候应该注意, 当前区间的最大的连续的1的数量 = 左子树最大的1的数量 右子树最大的1的数量 以及中间的最大的连续的1的数量 (这里wa了好久), 在query的时候应该注意控制区间长度。 代码如下: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 100000 + 100; int n; int a[maxn]; struct Segment{ int lsum0, lsum1, rsum0, rsum1; int msum0, msum1; int l, r; int ck; //翻转标记 }tree[3*maxn]; void push_up(int rt){ //回溯的时候利用儿子结点信息更新父亲 int ll = tree[rt<<1].r

杭电1698--Just a Hook(线段树, 区间更新)

孤人 提交于 2020-01-05 03:17:44
题目: http://acm.hdu.edu.cn/showproblem.php?pid=1698 线段树, 区间更新, 用到了Lazy思想。利用已更新区间来减少未更新区间用时。(自己的理解, 应该是对的) #include <cstdio> #include <cstring> #include <iostream> using namespace std; int Node[ 100100 << 2 ], n, m, lazy[ 100100 << 2 ]; void Pushup( int root) { Node[root] = Node[root<< 1 ] + Node[root<< 1 | 1 ]; } void Pushdown( int l, int r, int root) { int mid = (l + r) >> 1 ; Node[root<< 1 ] = (mid - l + 1 )*lazy[root]; Node[root<< 1 | 1 ] = (r - mid)*lazy[root]; lazy[root<< 1 ] = lazy[root<< 1 | 1 ] = lazy[root]; lazy[root] = 0 ; } void Build( int l, int r, int root) { lazy[root] = 0 ; if (l