线段树

COGS 265线段覆盖[线段树]

前提是你 提交于 2020-03-30 09:31:44
265. 线段覆盖 ★★☆ 输入文件: xdfg.in 输出文件: xdfg.out 简单对比 时间限制:2 s 内存限制:20 MB 【问题描述】 有一根长度为 L 的白色条状物。有两种操作: 用一条长度为 T 的黑布盖住条状物的 [a, a+T] 这个区间 (0<=a, T<=L) 。 把某条黑布拿走。 输入 L 和 n 次操作,要你输出每次操作之后: 条状物上有多少个黑区间。 条状物上黑区间的总长度。 【输入格式】 输入文件第一行两个整数 L(1<=L<=200000), n(1<=n<=200000) 以下有n行,第2--n+1行每行有3个整数m,a,T,m表示操作类型,1表示放入黑布,2表示拿走黑布,a,T表示黑布在L上的起始位置与长度,拿走的黑布保证是原来已经存在的. 【输出格式】 输出有n行,每行两个整数x,y,x表示L上的黑区间个数,y表示黑区间的总长度. 【输入输出样例】 输入: 20 4 1 5 3 1 7 2 2 5 3 1 16 3 输出: 1 3 1 4 1 2 2 5 需要维护的是区间个数和总长度 保存区间cnt,len,区间处理需要lazy标记,考虑合并需要知道左右断点是否覆盖,lcov和rcov 本题只需要考虑更新就可以了,没有查询操作 merge时考虑lazy标记 注意叶子节点直接处理 // // main.cpp // cogs265 // //

线段树练习2

随声附和 提交于 2020-03-30 09:21:16
题目传送: http://codevs.cn/problem/1081/ 1081 线段树练习 2 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 给你N个数,有两种操作 1:给区间[a,b]的所有数都增加X 2:询问第i个数是什么? 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。 输出描述 Output Description 对于每个询问输出一行一个答案 样例输入 Sample Input 3 1 2 3 2 1 2 3 2 2 3 样例输出 Sample Output 5 数据范围及提示 Data Size & Hint 数据范围 1<=n<=100000 1<=q<=100000 分类标签 Tags 点此展开 代码 #include<cstdio> #include<iostream> using namespace std; #define N 801000 #define mid ((l+r)>>1) #define lc (k<<1) #define

COdeVS——T 1082 线段树练习 3 (分块练习)

偶尔善良 提交于 2020-03-30 09:20:42
http://codevs.cn/problem/1082/ 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和。 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多少。 pascal选手请不要使用readln读入 输出描述 Output Description 对于每个询问输出一行一个答案 样例输入 Sample Input 3 1 2 3 2 1 2 3 2 2 2 3 样例输出 Sample Output 9 数据范围及提示 Data Size & Hint 数据范围 1<=n<=200000 1<=q<=200000 1 #include <cstdio> 2 #include <cmath> 3 4 using namespace std; 5 6 #define LL long long 7 const int N(500); 8 LL n,q,num[N*N],u,v,x,op; 9 10 LL C

(树链剖分+线段树)POJ - 3237 Tree

≡放荡痞女 提交于 2020-03-28 14:25:18
前言: 一直听说树链剖分-树链剖分,现在见识一下,,,感觉不是很难0.0 看了一下kuangbin模板基本秒懂 对于点,按重边优先给予每个点一个编号,对于一条重链上的点,编号则是连续的,将所有编号映射到线段树上,即可进行一切区间操作。 对于边的处理,我们将所有边对应到这条边节点更深的那个点上即可。 如果需要的操作只有求和,和单点更新/区间更新,直接用树状数组也是可以的,可能常数大那么一点点。 如果还需要更加强大的操作,显然用splay树维护也是可以的。。 比如树链上所有权值翻转等等。。不过,,这样差不多应该就快到LCT了。。虽然自己不会。。 不过过几天就该看了。 题意: 一棵树,每条边有一个权值,三种操作: 1、改变第i条边权值为v 2、将节点a到节点b之间的边权值取反 3、查询a到b之间最大的边权值 分析: 显然就是普通的树链剖分和线段树 但是要记得pushdown, 而对于lazy标记rev,当传下去的时候,不应该直接赋值为1或者0,而应该直接取反,用异或即可。 代码: 1 #include <math.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <time.h> 6 #include <algorithm> 7 #include <iostream> 8

POJ3237 Tree(树剖+线段树+lazy标记)

对着背影说爱祢 提交于 2020-03-28 14:22:30
You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms: CHANGE i v Change the weight of the i th edge to v NEGATE a b Negate the weight of every edge on the path from a to b QUERY a b Find the maximum weight of edges on the path from a to b Input The input contains multiple test cases. The first line of input contains an integer t ( t ≤ 20), the number of test cases. Then follow

cf1000F One Occurrence (线段树)

雨燕双飞 提交于 2020-03-27 05:54:58
这题我是离线做的 设i位置的数上次出现的位置是pre[i](如果第一次出现那就是0) 可以想到,用线段树维护一个区间的pre的最小值,如果它小于区间左端点,那这个数就是一个合法的答案 但直接这样做是错的 考虑1,2,3,4,[1,1],5,虽然前一个1的pre在区间外面,但他后面还有一个1啊 所以可以按照询问的右端点排序,推着来维护这个最小值 具体来说,对于i,先把i位置的值改成pre[i],然后如果有pre[i],那把pre[i]位置的值改成inf(一开始都要初始化成inf) 然后再查的话,我查到的就都是这个区间里的最后一次出现的那个数了,就不会有锅 1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=5e5+10; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c

hdu4107Gangster 线段树

自闭症网瘾萝莉.ら 提交于 2020-03-23 22:00:07
题目链接: http://icpc.njust.edu.cn/Problem/Hdu/4107/ 题目给定一个初始值都是零的序列,操作只有一种,就是给一个区间加上一个数,但是当一个数大于等于给定的P的时候就会在这个数上加上两倍的C,否则加上一倍的C。对于这种区间修改以及最终查询的问题我们首要想到的就是线段树,但是如果每次都到达点信息时才进行修改就时间复杂度太高了。对于一个区间中的数,我们可以维护最大值和最小值,只要最小值大于等于P,那么就所有的值都是大于等于P的,对他们的加法tag进行操作即可,对于一个区间,如果最大值小于P,则所有的数都是小于等于P的,对这个区间的tag加上C即可,更新时如果区间不满足在这个性质则需要继续向下更新。这题中只需要tag即可,最后加法tag全部推到最底层进行递归输出。 代码如下: 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9

集训队8月17日

跟風遠走 提交于 2020-03-21 01:11:32
刷题数:6 最近几天学了线段树,学得很仔细。里面的代码都基本会敲,算法原理也都懂了,扫描线也懂了。 线段树就是每个节点代表一个区间,然后左右节点除2缩小,数组下标乘2变大。用来对序列进行维护,支持查询修改。 而扫描线我在第三篇博客里有提起我对这个算法的理解。 算法竞赛进阶指南210~213页。 线段树求最大子段和 https://www.cnblogs.com/2462478392Lee/p/11368762.html 线段树+差分 https://www.cnblogs.com/2462478392Lee/p/11359868.html 线段树扫描线 https://www.cnblogs.com/2462478392Lee/p/11368866.html 线段树权值扫描线 https://www.cnblogs.com/2462478392Lee/p/11368976.html 总结 感觉自己学得有点慢了,但又觉得受益匪浅。 来源: https://www.cnblogs.com/2462478392Lee/p/11369031.html

POJ 3667 Hotel (线段树区间合并)

僤鯓⒐⒋嵵緔 提交于 2020-03-19 00:23:22
题目链接: http://poj.org/problem?id=3667 题目大意:一共有n个房间,初始时都是空的,现在有m个操作,操作有以下两种: 1.1 d :询问是否有连续d个空的房间,若有则输出连续房间的起始编号,若无则输出0 2.2 xi d:将第xi个房间至第xi+d-1个房间清空 解题思路:线段树维护区间最大连续长度,tree[cur].lm代表以区间左端点为起点的连续段的长度 tree[cur].rm代表以区间右端点为终点的连续段的长度,tree[2*cur].rm+tree[2*cur+1].lm代表包含该区间中点的连续段的长度 这是个隐含值(中间连续段),则区间内最长连续段值不止要从左右子节点的最长连续段中择最大 还要考虑该区间的中间连续段即tree[cur].len=max(tree[2*cur].rm+tree[2*cur+1].lm,max(tree[2*cur].len,tree[2*cur+1].len)); 代码: #include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; const int maxn=50007; int n,m; struct node{ int lm,rm,len,cov; }tree[maxn

线段树模板 (刘汝佳)

眉间皱痕 提交于 2020-03-19 00:19:19
一、线段树( 点修改 ) Update(x,v): 把Ax修改为v Query(L,R): 计算区间[qL,qR] 最小值。 代码: [cpp] view plain copy // Dynamic RMQ // Rujia Liu // 输入格式: // n m 数组范围是a[1]~a[n],初始化为0。操作有m个 // 1 p v 表示设a[p]=v // 2 L R 查询a[L]~a[R]的min #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF = 1000000000; const int maxnode = 1<<17; int op, qL, qR, p, v; //qL和qR为全局变量,询问区间[qL,qR]; struct IntervalTree { int minv[maxnode]; void update( int o, int L, int R) { int M = L + (R-L)/2; if(L == R) minv[o] = v; // 叶结点,直接更新minv else { // 先递归更新左子树或右子树 if(p <= M) update(o*2, L, M); else update(o*2+1, M+1, R)