线段树

Picture POJ - 1177 线段树+离散化+扫描线 求交叉图像周长

混江龙づ霸主 提交于 2020-02-11 21:48:12
参考 https://www.cnblogs.com/null00/archive/2012/04/22/2464876.html #include <stdio.h> #include <algorithm> #define LEN 10000 using namespace std; struct Node { int left; int right; int count;//被覆盖次数 //所包含的区间数量,如三条[1,2],[2,3],[4,5]线段被覆盖,则line=2,因为 [1,2],[2,3]是连续的。 int line;//所包含的区间数量 int lbd;//左端点是否被覆盖 用来辅助对line的计算 int rbd;//右端点是否被覆盖 int m;//测度 ,即覆盖的区间长度,如[2,8]就为6 }node[LEN*4];; struct ScanLine { int x; int y1; int y2; int flag; }scan[LEN];; int y[LEN]; void build(int l, int r, int i) { node[i].left = l; node[i].right = r; node[i].count = 0; node[i].m = 0; node[i].line = 0; if (r - l > 1) { int

前缀和+贪心+线段树——cf893D

∥☆過路亽.° 提交于 2020-02-11 21:20:52
/* 贪心策略: 如果检查的那天不用加,那就不加 反之加上尽可能多的钱 如何确定这个值? 处理出前缀和,第i天可以加的钱=d-[i+1,n]天里前缀和的最大值 加上这个值后,要再一次更新前缀和数组,用线段树维护前缀和数组即可 */ #include<bits/stdc++.h> using namespace std; #define ll long long #define N 200005 ll n,d,a[N],sum[N]; vector<int>v; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 ll lazy[N<<2],Max[N<<2]; void pushdown(int rt){ lazy[rt<<1]+=lazy[rt]; lazy[rt<<1|1]+=lazy[rt]; Max[rt<<1]+=lazy[rt]; Max[rt<<1|1]+=lazy[rt]; lazy[rt]=0; } void build(int l,int r,int rt){ if(l==r){Max[rt]=sum[l];return;} int m=l+r>>1; build(lson);build(rson); Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); } void update(int L

BZOJ #5457: 城市 [线段树合并]

半城伤御伤魂 提交于 2020-02-11 20:57:55
线段树合并的板子题,每次从下到上合并就完事了 // by Isaunoya #include <bits/stdc++.h> using namespace std; #define rep(i, j, n) for (int i = j; i <= n; i++) #define in cin #define out cout #define pii pair<int, int> #define fir first #define sec second int n, m; const int maxn = 4e5 + 54; int rt[maxn], ls[maxn << 5], rs[maxn << 5], cnt = 0; pii mx[maxn << 5], ans[maxn]; void upd(int& p, int l, int r, int x, int v) { if (!p) p = ++cnt; if (l == r) { mx[p] = { v, -x }; return; } int mid = l + r >> 1; if (x <= mid) upd(ls[p], l, mid, x, v); else upd(rs[p], mid + 1, r, x, v); mx[p] = max(mx[ls[p]], mx[rs[p]]); } int

Mayor's posters POJ - 2528 线段树区间覆盖

青春壹個敷衍的年華 提交于 2020-02-11 08:35:13
//线段树区间覆盖 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=100010; int flag; struct node{ int l,r; //vis 是这块区域是否完全被覆盖 bool vis; }tr[N<<2]; struct point { int id; int x; }post[N<<2]; int cmp1(point a,point b) { return a.x<b.x; } int cmp2(point a,point b) { if(a.id==b.id) return a.x<b.x; return a.id>b.id; } void pushup(int u) { tr[u].vis=tr[u<<1].vis&&tr[u<<1|1].vis; } void build(int u,int l,int r) { tr[u]={l,r,0}; if(l==r) return ; int mid=l+r>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); } void query(int u,int l,int r) { if(tr[u].vis)

动态点分治

被刻印的时光 ゝ 提交于 2020-02-10 21:55:26
一搬都是动态修改点权时我们使用动态点分治来保证时间复杂度. 这里说一下深刻的理解,首先建出点分树并不难我们只需要记一个fa甚至不需要记儿子就能维护出来这样的一棵树. 为什么要维护这样的一棵树下面根据例题具体论述: bzoj3730震波 1. 每次查询距离x距离不超过y的点权之和. 2. 点权有修改. 3. 强制在线. 如果光有1怎么办我们可以考虑一下换根,好像父亲的信息很难维护 不可行。 点分治?好像也不行,有一种做法是每个点维护主席树然后再暴力向上跳统计答案+去重。 其实如果没有强制在线这类似于三维数点问题,由于我学艺不精不会数点... 好像我们第二种思路就是复杂度高了一点,那么细致的讲下一下第二种思路吧. 每个点维护其子树内距离为d的点权和具体的我们可以使用线段树合并来保证复杂度. 考虑一下查询首先是在x处查询,x暴力跳父亲在父亲处查询此时注意容斥把x处y-1的距离减掉即可. 那么修改呢?同样是暴力修改点权但是好像这里空间开销过大 时间也是如此极其不优秀。 原因?我们可能要从一条链的底部跳到链的顶头很难受。 其实我们这样做的原因只是为了检索到所有的答案罢了. 所以可以用点分树这棵树来进行暴力检索答案的过程由于树非常的平衡logn 所以时间和空间上都是可以承受的。 具体的这能完全体现出检索答案的过程么? 在x点询问 我们直接在点分树中的x点所维护的主席树中查询,然后跳点分树的父亲

清北学堂—2020.1提高储备营—Day 2 afternoon

旧时模样 提交于 2020-02-09 18:47:09
qbxt Day 2 afternoon ——2020.1.18 济南 主讲:李佳实 目录一览 1.线段树 2.二叉搜索树(略过) 3.树状数组 总知识点:基础数据结构(本人初学感觉好难) 一、线段树 1.描述:线段树是一种分治的思想,用树形结构把一个大区间划分成小区间,它同时又是一棵二叉树。 2.概念名词定义: 区间(又称线段):线段树上的每一个节点对应于一个区间[a,b]。(a,b为整数) 特殊说明:对于叶子节点,其对应的区间长度为1。 For Example: (1)区间[1,10]对应的线段树 (2)区间[1,9]对应的线段树 3.性质:对于每一个非叶结点所表示的结点[a,b],其左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b](除法去尾取整) 4.基本操作: (1)线段树的存储:类似于堆 对于一棵线段树,它的根节点下标为1。 其下标为i的节点,它的左儿子下标为2i,右儿子下标为2i+1。 (2)线段树核心操作:区间分解 定义:若线段树根节点对应区间为[a,b],给定区间 c,d ,找出一些节点,使这些节点对应的区间互相不重叠,且加起来正好是[c,d],这样的操作过程即区间分解。 代码核心思想:二分 操作步骤:(递归分解) 1.从根节点出发,开始区间分解 2.遇到节点[x,y]时,如果要分解的区间就是[x,y],即为找到一个终止节点

牛客3 F/G 牛牛的Link Power |线段树区间修改

梦想的初衷 提交于 2020-02-09 17:13:27
F题 牛牛的Link Power I https://ac.nowcoder.com/acm/contest/3004/F 思路 每个“1”对于它本身位置产生的影响贡献为0,而往后面依次产生了0,1,2,3,4,5...的贡献。 参考下图,对于值为1的i号点,我们把线段树叶节点维护的[i+1,n]的值都+1(区间修改);每次查询值为1的点,query(1,i),查询出i点前所有为1的点对它的能量贡献,累加就可以了。 建一颗线段树,区间修改,区间求和,累加查询i点前所有为1的点对i点的能量贡献即可。 为什么区间+1之后,可以用线段树查询i点前所有为1的点对i点的能量贡献, 因为 对于i点将[i+1,n]都加1,相当于把它影响到的点都权值+了1; 不好理解的话,就参考下图的例子 AC代码 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5+10; const ll mod = 1e9+7; int n,q,a[maxn]; char s[maxn]; ll sumv[maxn<<2],addv[maxn<<2]; //合并 void pushup(int o){ sumv[o] = sumv[o<<1] + sumv[o<<1|1]; } //建树 void

线段树单点修改、区间修改、单点查询值、区间查询最大值、最小值、区间和之模板

烂漫一生 提交于 2020-02-09 14:37:49
毕生所学。 1 const int N = 2e5 + 10; 2 #define lson rt << 1 // == rt * 2 左儿子 3 #define rson rt << 1 | 1 // == rt * 2 + 1 右儿子 4 #define int_mid int mid = tree[rt].l + tree[rt].r >> 1 5 int a[N]; // 初始值 6 struct node { 7 int l, r; 8 ll val, lazy; 9 } tree[N * 4]; 10 void push_up(int rt) { 11 //tree[rt].val = min(tree[lson].val, tree[rson].val); 12 //tree[rt].val = max(tree[lson].val, tree[rson].val); 13 tree[rt].val = tree[lson].val + tree[rson].val; 14 } 15 void push_down(int rt) { 16 if (tree[rt].lazy) { 17 tree[lson].lazy += tree[rt].lazy; 18 tree[rson].lazy += tree[rt].lazy; 19 //{ // 维护最大最小值 20

洛谷 P4513 小白逛公园

删除回忆录丶 提交于 2020-02-08 22:06:19
题目背景 小新经常陪小白去公园玩,也就是所谓的遛狗啦… 题目描述 在小新家附近有一条“公园路”,路的一边从南到北依次排着 n n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。 一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第 a a个和第 b b个公园之间(包括 a a、 b b两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。 那么,就请你来帮小白选择公园吧。 输入格式 第一行,两个整数 N N和 M M,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。 接下来 N N行,每行一个整数,依次给出小白 开始时对公园的打分。 接下来 M M行,每行三个整数。第一个整数 K K, 1 1或 2 2。 K=1 K = 1表示,小新要带小白出去玩,接下来的两个整数 a a和 b b给出了选择公园的范围( 1≤a,b≤N 1 ≤ a , b ≤ N)。测试数据可能会出现 a>b a > b的情况,需要进行交换; K=2 K = 2表示,小白改变了对某个公园的打分,接下来的两个整数 p p和 s s,表示小白对第 p p个公园的打分变成了 s s( 1≤p≤N 1 ≤ p ≤ N)。 其中, 1≤N≤500 000

KPI(HDU—5249)权值线段树

主宰稳场 提交于 2020-02-08 17:52:54
题目传送门 Problem Description 你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度。数十亿的请求被推到一个大管道后同时服务从管头拉取请求。让我们来定义每个请求都有一个重要值。我的KPI是由当前管道内请求的重要值的中间值来计算。现在给你服务记录,有时我想知道当前管道内请求的重要值得中间值。 Input 有大约100组数据。 每组数据第一行有一个n(1≤n≤10000),代表服务记录数。 接下来有n行,每一行有3种形式 “in x”: 代表重要值为x(0≤x≤109)的请求被推进管道。 “out”: 代表服务拉取了管道头部的请求。 "query: 代表我想知道当前管道内请求重要值的中间值. 那就是说,如果当前管道内有m条请求, 我想知道,升序排序后第floor(m/2)+1th 条请求的重要值. 为了让题目简单,所有的x都不同,并且如果管道内没有值,就不会有"out"和"query"操作。 Output 对于每组数据,先输出一行 Case #i: 然后每一次"query",输出当前管道内重要值的中间值。 Sample Input 6 in 874 query out in 24622 in 12194 query Sample Output Case #1: 874 24622 这道题的解决方法也有好几种