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;}
原创粉丝点击