Interval prescribing segment tree

Outline

  Segment tree data structure is practical, in line with arithmetic operations to support all sections of associativity. But evolution does not comply with binding law, how to maintain it with the tree line? In fact, the segment tree can not support itself, but there are ways to maintain a limited time, it is the use of the number of times the square root after experiencing will tend to optimize the uniform nature of the operation.

data structure

  Thought section prescribing segment tree as shown above, is the use of square root properties, calculated in the first violence in several sets of data, perform simple arithmetic post The continuous uniform sequence. For two common problems, there are two approaches.

Only an interval of prescribing

  We can find any number having gone through a few times the square root will be equal to 0, so we can easily think of several operations will initially calculated violence, and record the maximum. Because $ 18 $ 10 ^ 6 prescribing and experienced after rounding down is equivalent to a 1, the count up violence $ $ 6N times, the complexity of $ \ Theta (N) $. And after that, we had no more than a maximum range of 1 can not be the operation. ($ \ Sqrt {1} = 1, \ sqrt {0} = 0 $)

  As for implementation, simpler than ordinary tree line, no lazy_tag, only need to maintain and operate to the maximum range required, a special judge in Riga update function can be optimized computing.

Example: States Luogu P4145 God made the title of seven minutes 2 / Flora travel 

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF=1e9+7,MAXN=1e5+10,MAXNODE=MAXN*4;
int N,M;
LL tmp[MAXN],sum[MAXNODE],maxv[MAXNODE];
inline void push_up(int x){
    sum[x]=sum[x<<1]+sum[x<<1|1];
    maxv[x]=max(maxv[x<<1],maxv[x<<1|1]);
}
void init(int x,int l,int r){
    if(l==r){
        sum[x]=maxv[x]=tmp[l];
        return;
    }
    int mid=(l+r)>>1;
    init(x<<1,l,mid);
    init(x<<1|1,mid+1,r);
    push_up(x);
}
LL query(int x,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr)
        return sum[x];
    int mid=(l+r)>>1;
    LL ret=0;
    if(ql<=mid)
        ret+=query(x<<1,l,mid,ql,qr);
    if(mid<qr)
        ret+=query(x<<1|1,mid+1,r,ql,qr);
    return ret;
}
void update(int x,int l,int r,int ql,int qr){
    if(l==r){
        maxv[x]=sqrt(maxv[x]);
        sum[x]=sqrt(sum[x]);
        return;
    }
    if(maxv[x]<=1)
        return;
    int mid=(l+r)>>1;
    if(ql<=mid&&maxv[x<<1]>1)
        update(x<<1,l,mid,ql,qr);
    if(mid<qr&&maxv[x<<1|1]>1)
        update(x<<1|1,mid+1,r,ql,qr);
    push_up(x);
}
int main(){
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
        scanf("%lld",tmp+i);
    init(1,1,N);
    scanf("%d",&M);
    for(int i=1,k,l,r;i<=M;i++){
        scanf("%d%d%d",&k,&l,&r);
        if(l>r)
            swap(l,r);
        if(k)
            printf("%lld\n",query(1,1,N,l,r));
        else
            update(1,1,N,l,r);
    }
    return 0;
}

 

Note: Support for other operating segment tree does not support this issue, because there is no interval plus, there will be a lot of 0, equal to the range will be very small.

Other operations support

  When prescribing binding and rounding down, and there |, so that a similar operation & data convergence effect. So we just need to perform several operations before the violence, equality for the back, just for a range of special judge, if it will equal intervals and other indicators of direct evolution, after all, convergence is irreversible.

Example: the underlying data structures Exercises : xiaowuga Gangster code

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
long long a[N];
struct node{
    int l,r;
    long long maxx,minn,sum;
    long long lazy;
    void up(long long val){
        maxx+=val;minn+=val;sum+=(r-l+1)*1ll*val;
        lazy+=val;
    }
}tree[8*N];
void push_up(int x){
    tree[x].maxx=max(tree[x<<1].maxx,tree[x<<1|1].maxx);
    tree[x].minn=min(tree[x<<1].minn,tree[x<<1|1].minn);
    tree[x].sum=tree[x<<1].sum+tree[x<<1|1].sum;
}
void push_down(int x){
    long long val=tree[x].lazy;
    if(val){
        tree[x<<1].up(val);
        tree[x<<1|1].up(val);
        tree[x].lazy=0;
    }
}
void build(int x,int l,int r){
    tree[x].l=l;  tree[x].r=r; 
    tree[x].lazy=tree[x].sum=0;
    if(l==r){
        tree[x].minn=tree[x].maxx=tree[x].sum=a[l];
        return;
    }
    int m=(l+r)/2;
    build(x<<1,l,m);
    build(x<<1|1,m+1,r);
    push_up(x);
}
void updata(int x,int l,int r,long long val){
    int L=tree[x].l,R=tree[x].r;
    if(l<=L&&R<=r){
        tree[x].up(val);return;
    }
    int m=(L+R)/2;
    push_down(x);
    if(l<=m) updata(x<<1,l,r,val);
    if(r>m) updata(x<<1|1,l,r,val);
    push_up(x);
}
void Sqrt(int x,int l,int r){
    push_down(x);
    int L=tree[x].l,R=tree[x].r;
    if(l<=L&&R<=r){
        if(tree[x].maxx==tree[x].minn){
            long long t=(long long)sqrt(tree[x].maxx);
            updata(x,L,R,t-tree[x].maxx);
            return;
        }
        else if(tree[x].minn+1==tree[x].maxx){
            long long t1=(long long)sqrt(tree[x].minn); 
            long long t2=(long long)sqrt(tree[x].maxx); 
            if(t1+1==t2){
                updata(x,L,R,t2-tree[x].maxx);
                return;
            }
        }
    }
    int m=(L+R)/2;
    if(l<=m) Sqrt(x<<1,l,r);
    if(r>m) Sqrt(x<<1|1,l,r);
    push_up(x);
}
long long query(int x,int l,int r){
    push_down(x);
    int L=tree[x].l,R=tree[x].r;
    if(l<=L&&R<=r){
        return tree[x].sum;
    }
    int m=(L+R)/2;
    long long ans=0;
    if(l<=m) ans+=query(x<<1,l,r);
    if(r>m) ans+=query(x<<1|1,l,r);
    push_up(x);
    return ans;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    build(1,1,n);
    while(m--){
        int op,l,r;
        scanf("%d%d%d",&op,&l,&r);
        if(op==1){
            long long val;
            scanf("%lld",&val);
        }1
            updata (,l,r,val);
        else if(op==2){
            Sqrt(1,l,r);
        }
        else{
            printf("%lld\n",query(1,l,r));
        }
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/guoshaoyang/p/11228109.html