线段树

poj2750 Potted Flower[线段树]

蹲街弑〆低调 提交于 2019-11-28 13:45:36
求一个环待修改最大连续子段和且不能全部选上。 先断环,在$1 \sim n$的链上,考虑没有限制全选的最大连续子段和。显然最大解只有两种情况,一种是这个,一种是另一个。 第一个可以直接套路维护,第二个无非就是整体的和减去最小连续子段和。两者取一个最大的就行了。 然后考虑到如果全选的情况。这种情况下只能被迫采取第二种选法。也就是特判若第一种选法等于当前区间和,则强制用第二种(可以证明肯定是对的,且这个其实有漏洞,但是答案不会错)。于是无脑码一波segment_tree即可。 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define dbg(x) cerr<<#x<<" = "<<x<<endl 7 using namespace std; 8 typedef pair<int,int> pii; 9 typedef long long ll; 10 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} 11 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} 12

CPU监控 线段树裸题

北城余情 提交于 2019-11-28 13:24:49
LINK: bzoj3064 此题甚好码了20min停下来思考的时候才发现不对的地方有点坑... 还真不好写来着 可这的确是线段树的裸题...我觉得我写应该没有什么大问题 不过思路非常的紊乱 如果是自己写的话 所以为了自己能写出来 整理思路就是这篇博客了。 Q X Y:询问从X到Y这段时间内CPU最高使用率 A X Y:询问从X到Y这段时间内之前列出的事件使CPU达到过的最高使用率 P X Y Z:列出一个事件这个事件使得从X到Y这段时间内CPU使用率增加Z C X Y Z:列出一个事件这个事件使得从X到Y这段时间内CPU使用率变为Z 4个询问 观察如果没有第二个询问的话那么这将是一个线段树维护两个标记且维护区间最大值的操作 很好写。 能否标记永久化?学了就应该思考一下能否标记永久化 好像有点繁杂两个标记互相干扰 不过应该没有什么大问题 但是加上区间最值就不太好写了 所以对于多个标记且互相影响且维护历史最值应该是做不了的 建议pushdown更好一点。 综上 线段树 的lazy tag 和标记永久化都是选自哪一种好写写哪一个,这里推荐写lazy tag代码复杂度不算太高。 考虑如何维护历史最值 这个z可能是负数 如果简单的开一个标记mx表示历史最值的话对于一次区间 的修改 考虑一件事情pushdown未传递之时一个区间覆盖的标记打过来直接add标记被覆盖掉么 那么历史最值可就会出错

hdu 6703 权值线段树

巧了我就是萌 提交于 2019-11-28 13:08:04
  题意: 给出一个1-n的全排列 a 操作1:修改a[pos] 为 a[pos]+1000000 操作2: 问k的所有后继中(包括k) 最小的 且与a[1]-a[r]均不相等的数是多少 n<=1e5 #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ///////////////////////////////////// const int N=2e6+10; int maxx[N<<2],position[N]; void up(int pos) { maxx[pos]=max(maxx[pos<<1],maxx[pos<<1|1]); } void build(int l,int r,int pos) { if(l==r){maxx[pos]=position[l];return ;} int m=(l+r)

第k小问题

杀马特。学长 韩版系。学妹 提交于 2019-11-28 12:58:03
例题1:[poj2104]K-th Number(区间第k小模板题)    题意: 询问给定序列静态区间第k小   0.将区间第k小/大转化为存在k个数小于等于/大于等于它且最小/大的数(挺有用的)   1.可持久化线段树(主席树)/可持久化字典树,这里就不写了(在线)   2.分块,询问先二分答案,相当于求小于等于它的数个数,整块用暴力排序(初始)+二分/预处理(不用排序)来解决,散块暴力(在线) 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define K 1000 6 #define N 100005 7 #define bl(k) ((k-1)/K) 8 int n,m,x,y,z,a[N],b[N],sum[N/K][N]; 9 int calc(int l,int r,int k){ 10 int s=0; 11 for(int i=bl(l)+1;i<bl(r);i++)s+=sum[i][k]; 12 for(int i=l;i<=min(bl(l)*K+K,r);i++)s+=(a[i]<=k); 13 if (bl(l)!=bl(r)) 14 for(int i=bl(r)*K+1;i<=r;i++)s+=(a[i]<=k); 15

线段树

只谈情不闲聊 提交于 2019-11-28 11:26:13
1.概念: 线段树将一个区间划分为多个单元区间,每个单元区间对应线段树中的一个叶子结点。 2.功能: 主要用于高效解决连续区间的动态查询问题。 3.性质: 根节点【m,n】 , 左子树【m,(m+n)/2】,右子树【(m+n)/2+1,n】 4.离散化   离散化是为了解决数据范围太大的情况,不改变其相对大小,用小数来替代大数,                                  个人模板: 线段树的定义: const int maxn=200005; ///线段树的定义 int a[maxn]; struct node { int l,r; int CC;///CC可以代表sum,min,max等,依据自己定义, }tree[maxn*4]; 建树 void build_tree(int root,int l,int r) { tree[root].l=l; tree[root].r=r; if(l==r) { tree[root].CC=a[l]; return; } int mid=(l+r)/2; build_tree(root*2,l,mid); build_tree(root*2+1,mid+1,r); tree[root].CC=max(tree[root*2].CC,tree[root*2+1].CC); } 单点更新(是区间更新的特例) update

权值线段树

余生长醉 提交于 2019-11-28 11:12:18
array 题意 给出一个 1,n 的排列,有q(q<=1e5)有以下两个操作(强制在线): 1.给位置pos上的数+1e7 2.询问[1,r]区间上大于等于k(1e5)的数最小是多少(这个数不能等于[1,r]区间中的任意一个数) 分析 由数据我们可以知道只要对一个数进行了操作1,相当于把这个数挖掉了,所以我们想要找到最小的满足题意的值,只需要维护区间最大值,只要区间中有值大于等于k,就可以进区间找,但是这样会带来很多问题,首先是区间全是连续的无法插,其次是可以插,如何找到这个空?这个时候需要转化思维,既然普通线段树难以维护,是否考虑主席树or权值线段树,使用权值线段树,维护区间最大的标号,如果标号大于等于r,先往左边找,但是这样可能会导致[1,mid]中有标号比r大的,但是比k小,这样就会一直找到mid,只需要开一个变量记一下,如果[1,mid]不合法继续到右子树找就行了(比赛的时候心态崩了这么简单处理都不会了,要是冷静下来改改就过了) #include<bits/stdc++.h> using namespace std; const int maxn=1e5+4; const int inf=0x3f3f3f3f; int tr[maxn<<2]; int a[maxn],b[maxn],vis[maxn]; void build(int o,int l,int r){ if

luoguP2486 [SDOI2011]染色

一曲冷凌霜 提交于 2019-11-28 11:07:22
题目 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1、将节点a到节点b路径上所有点都染成颜色c; 2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。 请你写一个程序依次完成这m个操作。 Sample Input 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q 3 5 C 5 1 2 Q 3 5 Sample Output 3 1 2 HINT 数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。 分析 我实在是懒得分析了emm...这题目调了半天!!! 还是写写吧 正解: 树剖+线段树 因为要判断颜色的段数,所以想到在线段树里要维护个左右端点的颜色,并且在查询的时候要判断颜色,为了防止算重复。 线段树的操作就不写了( 垃圾博主就是忘了写下传tag到儿子的tag, 他脑子让驴给踢了,不用管他 )(注意, 线段树的query可能要变一下 ),考虑查询操作:当前链与上一次的链在相交的边缘可能颜色相同,如果颜色相同答案需要减一。所以统计答案的时候要记录下 上一次 剖到的 链所在线段树区间 的 左端点 , 每次与当前链所在线段树的右端点 比较(想想 线段树的查询 和 in[]数组 )

敌兵布阵 HDU 1166 线段树

喜夏-厌秋 提交于 2019-11-28 11:02:29
敌兵布阵 HDU 1166 线段树 题意 这个题是用中文来描写的,很简单,没什么弯。 解题思路 这个题肯定就是用线段树来做了,不过当时想了一下可不可用差分来做,因为不熟练就还是用了线段树来做,几乎就是模板题了。 代码实现 #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<iostream> # define ls (rt<<1) # define rs (rt<<1|1) using namespace std; const int maxn=5e4+7; struct node{ int l, r; int sum, lazy; }t[maxn<<2]; int num[maxn]; int n, m; void up(int rt) { t[rt].sum=t[ls].sum+t[rs].sum; } void build(int rt, int l, int r) { t[rt].l=l; t[rt].r=r; t[rt].lazy=0; if(l==r) { t[rt].sum=num[l]; return ; } int mid=(l+r)>>1; build(ls, l, mid); build(rs, mid+1, r); up(rt); } void

CodeForces 877E DFS序+线段树

谁说我不能喝 提交于 2019-11-28 11:00:36
CodeForces 877E DFS序+线段树 题意 就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身一共有几个灯是亮的。pow x,表示你需要改变x的子树和x本身上的灯的状态。 题解思路 这个题肯定是用DFS序了,为啥?因为树不好操作啊(我也不会啊),使用DFS序可以把树压成一维的一串数,这样就可以使用线段树来进行区间操作了。 话说这个题是我暑假限时训练中做的,看到这个题老开心了,但是让我万万没想到的是,这个题我交了11次才过,太心酸了。 代码实现 #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<iostream> #include<vector> using namespace std; const int maxn=2e5+100; struct node{ int l, r; int sum; int lazy; }t[maxn<<2]; vector<int> g[maxn]; int num[maxn]; int in[maxn], out[maxn], rk[maxn], cnt; int n, m; void dfs(int u, int fa) // {

CodeForce 855B 暴力or线段树

笑着哭i 提交于 2019-11-28 10:57:47
CodeForce 855B 暴力or线段树 题意 给你一串数,然后找出三个数,他们的前后关系和原来一样,可以相同,然后分别乘p,q,r,求他们积的和最大,并且输出这个数。 解题思路 这个可以使用线段树来做,找出区间内的最小值和最大值,如果x(代表pqr中的一个)小于零,就乘以这个区间的最小值,如果大于零,就乘以这个区间的最大值。然后 \(j\) 从1到n开始遍历。 或者可以暴力,不过这个暴力比一点重方法还要好,我看完就惊呆了,lxm大佬太强了。 代码实现 第一种: #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<iostream> #include<cmath> # define ls (rt<<1) # define rs (rt<<1|1) using namespace std; typedef long long ll; const ll inf=0x3f3f3f3f3f3f3f3f; //注意这里是8个3f,用来初始化用,很重要。 const int maxn=1e5+7; struct node{ int l, r; ll ma, mi; }t[maxn<<2]; ll num[maxn]; ll n, p, q, r; void up(int rt) {