记录一个菜逼的成长。。
网上好多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;
}