线段树

HDU-4747 Mex(线段树区间更新)

一曲冷凌霜 提交于 2020-01-05 03:12:41
题目大意:给一个长度为n的整数序列,定义mex(i,j)表示区间[i,j]中没有出现过的最小非负整数,求sigma(mex(i,j)),即序列中所有连续非空子区间的mex之和。 题目分析: answer=mex(1,1)+mex(1,2)...mex(1,n) + mex(2,2)...mex(2,n) . . . + mex(n,n)。   初始时,用线段树的叶子节点维护mex(1,i),将a(1)从序列中拿去后,将叶子节点的维护信息更新为mex(2,i),以此类推...没更新一次,便求一次区间和,总和即为答案。   当拿掉a(i)后,只有a(k)以前的mex(i+1,j)将会受到影响,其中k>i并且a(i)=a(k)。   当i+1<=j<k时,如果mex(i,j)>a(i),那么mex(i+1,j)=a(i),否则mex(i+1,j)=mex(i,j)。显然,当 i 固定时,mex(i,j)关于 j 单调不减。所以,mex(i,j)>a(i)的将会是一段区间。 代码如下: # include<bits/stdc++.h> using namespace std; # define LL long long # define mid (l+(r-l)/2) const int N=200000; int a[N+5]; int mex[N+5]; int nxt[N+5];

【POJ2750】最大连续和 线段树

£可爱£侵袭症+ 提交于 2020-01-05 03:12:17
题目描述   给出一个含有N个结点的环,编号分别为1..N,环上的点带有权值(可正可负),现要动态的修改某个点的权值,求每次修改后环上的最大连续和,但不能是整个序列的和。 题目大意 单点修改,求环上的最大和。 数据范围 (4<=N,M<=100000)(不会爆int) 样例输入 5 3 -2 1 2 -5 4 2 -2 5 -5 2 -4 5 -1 样例输出 4 4 3 5 解题思路   线段树,维护:↓(最大值与最小值是指这一段的和的最大值与最小值) Max(区间最大值),MaxL(从左端开始的区间最大值),Maxr(从右端开始的区间最大值) Min(区间最小值),MinL(从左端开始的区间最小值),Minr(从右端开始的区间最小值) Sum(区间和),MinMin(这个东西我也不确定是否为必须的,以前做没有修改的环上的最大和时用过的,就加上吧233)   所以对环上最大和的询问的Ans就是(1-n这个区间的最大值)和(Sum-区间最小值)中的最大值A.A 代码 #include <bits/stdc++.h> using namespace std; inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch

线段树->面积并 Atlantis HDU - 1542

孤街醉人 提交于 2020-01-05 03:12:06
题目链接:https://cn.vjudge.net/problem/HDU-1542 题目大意:求面积并 具体思路:我们首先把矩形分割成一横条一横条的,然后对于每一个我们给定的矩形,我们将储存两个点,一个是左下角,一个是右上角。对于左下角的点,我们将他标记为-1,对于右上角的点,我们把它标记成1,-1代表这块区域的面积是需要减去的,1代表这块区域的面积是需要加上的,然后我们通过扫描线的形式,从y轴从下往上扫就可以了。 离散化的过程,数组还是尽量从0开始吧,因为在更新的过程中会出现0的情况,如果下标从1开始存储的话,会mle的,,,无限递归? ps:这个线段树的区间分开的时候和之前的不太一样,这个线段树{1,5}分开的是{1,3}和{4,5} 注意这个线段树每一个节点代表的是区间,节点1-3代表的是区间1-4,也就是 节点1代表 区间1-2 ,然后我们查询1-4 的时候,直接查询节点1-3就可以了,更新区间1-3的时候,更新节点1-2就可以了。 AC代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <string> 4 #include <cstring> 5 #include <algorithm> 6 #include <cmath> 7 #include <vector> 8 #include <queue> 9

poj 3667 线段树成端更新区间最大连续和

我们两清 提交于 2020-01-05 03:11:58
题目描述: 输入包括n,m,n表示现在一共有n个相邻的房间,m表示有m条命令。 1 a 表示现在来了一个人数为a的队伍,需要一个连续的区间能够容纳这么多人,如果能够容纳,输入最靠左边的房间的号码,否则输出0。 2 a,b 表示清空[a,a+b-1]区间内所有的房子 解题思路: 线段树结构体,定义需要记录的三个值,最大左连续、最大右连续、最大连续。 由上面的图可知,我们现在要更新两端区间,此时,合并区间的最大连续房间数只有三种情况: 1、 左区间最大连续房间数 2、 右区间最大连续房间数 3、 左区间最大右连续房间数 + 右区间最大左连续房间数 只要能够维护这些值,当中的更新和询问就好办了。 代码: View Code 1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 using namespace std; 5 const int N = 50005; 6 int mmax[N<<2],lmax[N<<2],rmax[N<<2],cover[N<<2]; 7 void PushDown(int t,int m) 8 { 9 if(cover[t]!=-1) 10 { 11 cover[t<<1]=cover[t<<1|1]=cover[t]; 12 mmax[t<<1]=lmax[t<<1]=rmax[t

线段树 & 题目

夙愿已清 提交于 2020-01-05 03:11:29
首先说下我写的线段树吧。 我是按照线段树【完全版】那个人的写法来写的,因为网上大多数题解都是按照他的写法来写。 确实比较飘逸,所以就借用了。 节点大小是maxn是4倍,准确来说是大于maxn的2^x次方的最小值的两倍。 lson 和 rson 用宏定义写了。因为是固定的量。 线段树不必保存自身的区间,因为一边传递过去的时候,在函数里就有区间表示,无谓开多些无用的变量。 pushUp函数,更新当前节点cur的值,其实就是,线段树一般都是处理完左右孩子,然后再递归更新父亲的嘛,这个pushUp函数就是用来更新父亲的。感觉不用这个函数更加清楚明了。 pushDown函数,在lazy--upDate的时候有用,作用是把延迟标记更新到左右节点。 多次使用sum不用清0,add要。build的时候就会初始化sum数据。但其他用法就可能要 1 #define lson L, mid, cur << 1 2 #define rson mid + 1, R, cur << 1 | 1 3 void pushUp(int cur) { 4 sum[cur] = sum[cur << 1] + sum[cur << 1 | 1]; 5 } 6 void pushDown(int cur, int total) { 7 if (add[cur]) { 8 add[cur << 1] += add[cur]

POJ 1151 Atlantis 线段树扫描线

旧街凉风 提交于 2020-01-05 03:10:32
$ \Rightarrow $ 戳我进POJ原题 Atlantis Time Limit: 1000MS $ \quad $ Memory Limit: 10000K   Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.   Input The input consists of several test cases. Each test case starts with a line containing a single integer $ n (1 \le n \le 100

ZOJ 2301/HDU 1199 线段树+离散化

旧街凉风 提交于 2020-01-05 03:10:20
给这个题目跪了两天了,想吐简直 发现自己离散化没学好 包括前一个离散化的题目,实际上是错了,我看了sha崽的博客后才知道,POJ那题简直数据弱爆了,本来随便一组就能让我WA掉的,原因在于离散化的时候,缩小数据规模的同时,没有考虑到误差,比如 1 4 6 8,离散化之后是1 2 3 4,我如果覆盖了1 2和3 4,表面上好像全部覆盖了,实际数据并没有覆盖。。所以我只能说那道题目我其实错了,并没有真正做出离散化出来。。。现在用这道题来弥补。 color the ball,ball的编号可以从1 到2^31,不可能开这么大线段树,但是其实测试数据只有N=2000*2组,所以必然是离散化,初始的时候,所有球都是黑色的,然后N组数组,a b w(b),说明把 区间 a到b染成(white or black),最后求最长的连续白色的区间的左右边界 瞬间想到上次求最大连续子串,线段树节点里用一个除了记录最大值,前驱最大值,后驱最大值以外,专门用个lm ,rm记录题目需要的坐标。这些都好处理,基本的线段树区间合并。要注意的是落实的叶子节点的时候,不能单纯以离散化之后的区间长度为衡量标准,要回到原区间去,原区间最长才是真正的最长。这个也好操作,读入数据的时候已经把原始区间保存下来了。 然后就是坑爹的离散化了,还是sha崽说得对,如果离散的两点距离大一1的话,必须要中间手动插点

线段树,区间更新

≯℡__Kan透↙ 提交于 2020-01-05 03:08:46
把一个区间内的值全部修改为一个确定值; 计算某个区间内的最大值,最小值,和。 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstdlib> 4 using namespace std; 5 #define INF 0x7f7f7f7f 6 #define Max 600000 7 long long a[Max], setv[Max], minv[Max], maxv[Max], sumv[Max], _max, _min, _sum, v; 8 int y1,y2; 9 bool flagv[Max]; 10 inline void maintain(int o, int L, int R) { 11 if (flagv[o]) minv[o] = maxv[o] = setv[o], sumv[o] = (R-L+1)*setv[o]; 12 else if (R > L) minv[o] = min(minv[o*2], minv[o*2+1]), maxv[o] = max(maxv[o*2], maxv[o*2+1]), 13 sumv[o] = sumv[o*2] + sumv[o*2+1]; 14 } 15 void build(int o, int L, int R) { 16 if (L == R)

LCIS(线段树区间合并)

 ̄綄美尐妖づ 提交于 2020-01-05 03:07:53
LCIS Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5912 Accepted Submission(s): 2563 Problem Description Given n integers. You have two operations: U A B: replace the Ath number by B. (index counting from 0) Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b]. Input T in the first line, indicating the case number. Each case starts with two integers n , m(0<n,m<=10 5 ). The next line has n integers(0<=val<=10 5 ). The next m lines each has an operation: U A B(0<=A,n , 0<=B=10 5 ) OR Q A B(0<=A<=B< n)

离散化+线段树/二分查找/尺取法 HDOJ 4325 Flowers

感情迁移 提交于 2020-01-05 03:07:39
题目传送门 题意:给出一些花开花落的时间,问某个时间花开的有几朵 分析:这题有好几种做法,正解应该是离散化坐标后用线段树成端更新和单点询问。还有排序后二分查找询问点之前总花开数和总花凋谢数,作差是当前花开的数量,放张图易理解: 还有一种做法用尺取法的思想,对暴力方法优化,对询问点排序后再扫描一遍,花开+1,花谢-1。详细看代码。 收获:一题收获很多:1. 降低复杂度可以用二分 2. 线段计数问题可以在端点标记1和-1 3. 离散化+线段树 终于会了:) ( 听说数据很水? ) 代码1:离散化+线段树 /************************************************ * Author :Running_Time * Created Time :2015-8-25 8:55:54 * File Name :F.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue>