zkw线段树
来源:互联网 发布:笔记本usb端口上的电涌 编辑:程序博客网 时间:2024/05/21 11:37
记录一个菜逼的成长。。
网上好多zkw线段树版本都是错的。。坑啊。
主要是连zkw的ppt上都是不完整和有错误的。统计的力量
结点信息
struct Node{ int sum,mx,mn;}T[maxn<<2];int M,a[maxn];
建树
void build(int n){ for( M = 1; M <= n+1; M <<= 1); for( int i = M + 1; i <= M + n; i++ )T[i].sum = T[i].mx = T[i].mn = a[i-M]; for( int i = M - 1; i; i-- ){ T[i].sum = T[i<<1].sum + T[i<<1|1].sum; //结点记录的是相对的值 T[i].mx = max(T[i<<1].mx,T[i<<1|1].mx); T[i<<1].mx -= T[i].mx;T[i<<1|1].mx -= T[i].mx; T[i].mn = min(T[i<<1].mn,T[i<<1|1].mn); T[i<<1].mn -= T[i].mn;T[i<<1|1].mn -= T[i].mn; }}
和的单点更新
for( T[x+=M].sum += v,x >>= 1; x; x >>= 1){ T[x].sum = T[x<<1].sum + T[x<<1|1].sum;}
最小(大)值的区间更新
区间更新也可以时单点更新(左端点等于右端点时
int s,t;// 只更新到当s,t是兄弟结点时for( s = x+M-1,t = x+M+1; s^t^1; s>>=1,t>>=1 ){ if(~s&1)T[s^1].mx += v,T[s^1].mn += v; if( t&1)T[t^1].mx += v,T[t^1].mn += v; A = max(T[s].mx,T[s^1].mx);T[s].mx -= A;T[s^1].mx -= A;T[s>>1].mx += A; A = max(T[t].mx,T[t^1].mx);T[t].mx -= A;T[t^1].mx -= A;T[t>>1].mx += A; A = min(T[s].mn,T[s^1].mn);T[s].mn -= A;T[s^1].mn -= A;T[s>>1].mn += A; A = min(T[t].mn,T[t^1].mn);T[t].mn -= A;T[t^1].mn -= A;T[t>>1].mn += A; } // 更新到根 while(s>1){ A = max(T[s].mx,T[s^1].mx),T[s].mx -= A,T[s^1].mx -= A,T[s>>1].mx += A; A = min(T[s].mn,T[s^1].mn),T[s].mn -= A,T[s^1].mn -= A,T[s>>=1].mn += A; }
和的区间查询
int querySum(int l,int r,int res = 0)//查询闭区间[l,r]{ // 看成开区间(l-1,r+1) for( l = l + M - 1,r = r + M + 1; l^r^1; l >>= 1,r >>= 1 ){ if(~l&1)res += T[l^1].sum; if( r&1)res += T[r^1].sum; } return res;}
最小(大)值的区间查询
int queryMax(int l,int r,int lmx = 0,int rmx = 0)// 查询闭区间[l,r]{ // 这里还是闭区间[l,r],跟和的查询不同 // 还要分是不是叶子结点 l += M,r += M; int res ; if(l != r){ for( ; l^r^1; l >>= 1,r >>= 1 ){ lmx += T[l].mx;rmx += T[r].mx; if(~l&1)lmx = max(lmx,T[l^1].mx); if( r&1)rmx = max(rmx,T[r^1].mx); } } res = max(lmx+T[l].mx,rmx+T[r].mx); while(l > 1)res += T[l>>=1].mx; return res;}
int queryMin(int l,int r,int lmn = 0,int rmn = 0){ l += M,r += M; int res = 0; if(l != r){ for( ; l^r^1; l >>= 1,r >>= 1 ){ lmn += T[l].mn;rmn += T[r].mn; if(~l&1)lmn = min(lmn,T[l^1].mn); if( r&1)rmn = min(rmn,T[r^1].mn); } } res = min(lmn+T[l].mn,rmn+T[r].mn); while(l > 1)res += T[l>>=1].mn; return res;}
完整模板
#include <stdio.h>#include <math.h>#include <string.h>#include <algorithm>using namespace std;const int maxn = 100000 + 10;struct Node{ int sum,mx,mn;}T[maxn<<2];int M,a[maxn];void build(int n){ for( M = 1; M <= n+1; M <<= 1); for( int i = M + 1; i <= M + n; i++ )T[i].sum = T[i].mx = T[i].mn = a[i-M]; for( int i = M - 1; i; i-- ){ T[i].sum = T[i<<1].sum + T[i<<1|1].sum; T[i].mx = max(T[i<<1].mx,T[i<<1|1].mx); T[i<<1].mx -= T[i].mx;T[i<<1|1].mx -= T[i].mx; T[i].mn = min(T[i<<1].mn,T[i<<1|1].mn); T[i<<1].mn -= T[i].mn;T[i<<1|1].mn -= T[i].mn; }}void update(int x,int v,int A = 0){ int s,t; for( s = x+M-1,t = x+M+1; s^t^1; s>>=1,t>>=1 ){ if(~s&1)T[s^1].mx += v,T[s^1].mn += v; if( t&1)T[t^1].mx += v,T[t^1].mn += v; A = max(T[s].mx,T[s^1].mx);T[s].mx -= A;T[s^1].mx -= A;T[s>>1].mx += A; A = max(T[t].mx,T[t^1].mx);T[t].mx -= A;T[t^1].mx -= A;T[t>>1].mx += A; A = min(T[s].mn,T[s^1].mn);T[s].mn -= A;T[s^1].mn -= A;T[s>>1].mn += A; A = min(T[t].mn,T[t^1].mn);T[t].mn -= A;T[t^1].mn -= A;T[t>>1].mn += A; } while(s>1){ A = max(T[s].mx,T[s^1].mx),T[s].mx -= A,T[s^1].mx -= A,T[s>>1].mx += A; A = min(T[s].mn,T[s^1].mn),T[s].mn -= A,T[s^1].mn -= A,T[s>>=1].mn += A; } for( T[x+=M].sum += v,x >>= 1; x; x >>= 1){ T[x].sum = T[x<<1].sum + T[x<<1|1].sum; }}int querySum(int l,int r,int res = 0){ for( l = l + M - 1,r = r + M + 1; l^r^1; l >>= 1,r >>= 1 ){ if(~l&1)res += T[l^1].sum; if( r&1)res += T[r^1].sum; } return res;}int queryMax(int l,int r,int lmx = 0,int rmx = 0){ l += M,r += M; int res ; if(l != r){ for( ; l^r^1; l >>= 1,r >>= 1 ){ lmx += T[l].mx;rmx += T[r].mx; if(~l&1)lmx = max(lmx,T[l^1].mx); if( r&1)rmx = max(rmx,T[r^1].mx); } } res = max(lmx+T[l].mx,rmx+T[r].mx); while(l > 1)res += T[l>>=1].mx; return res;}int queryMin(int l,int r,int lmn = 0,int rmn = 0){ l += M,r += M; int res = 0; if(l != r){ for( ; l^r^1; l >>= 1,r >>= 1 ){ lmn += T[l].mn;rmn += T[r].mn; if(~l&1)lmn = min(lmn,T[l^1].mn); if( r&1)rmn = min(rmn,T[r^1].mn); } } res = min(lmn+T[l].mn,rmn+T[r].mn); while(l > 1)res += T[l>>=1].mn; return res;}int main(){ return 0;}
阅读全文
0 0
- zkw线段树 运用
- 【zkw线段树】ural1855
- ZKW线段树
- POJ3468 ZKW线段树
- ZKW线段树
- zkw线段树 模板
- ZKW线段树
- zkw线段树
- zkw线段树
- zkw线段树分析
- ZKW 线段树
- zkw线段树
- zkw线段树详解
- zkw线段树
- poj3468 zkw线段树
- zkw线段树
- zkw线段树
- zkw线段树详解
- Java--种花的问题
- 浅析jQuery的基础设计模式
- 二叉树和二叉查找树
- C语言可以干些什么?C语言主要涉及哪些IT领域?
- Sublime Text Build 3126 x64 安装
- zkw线段树
- 说说 JavaScript 事件流之事件类型(包含 DOM2、DOM3 级事件)
- C# Lambda表达式
- Java多态的理解
- Android Vector Drawable | SVG 矢量图
- java Service和Servlet的区别 概念透析
- 提高C/C++运行效率以及避免出现Bug的20种方法
- 类加载机制
- 作为大型网站架构必须考虑的十大问题