线段树

线段树是一个神奇的数据结构,可以解决好多问题。
我第一次写的时候,写了3500+,结果,是错的。。。
我当时就笑了。。。
然后参(chao)考(xi)了某位大神的代码,才最终写出来了一份2000+的线段树。
话说,线段树这种数据结构支持在logn的时间内区间修改,区间求和,区间求最值等,是一种比较优秀的nlogn的数据结构。
我的代码比较简陋,以后可能还会更改。
下来贴代码:(这个是【洛谷P3372 线段树1】的代码)

#include<bits/stdc++.h>
#define ll long long
#define inf 9223372036854775807
using namespace std;
int n,m;
ll num[100001];
struct node{
    int l,r;
    ll sum,mx,mn,lazy;
}t[400001];
void pushup(int i){//更新一个区间,为了减少代码长度写了这个
    t[i].sum=t[i*2].sum+t[i*2+1].sum;
    t[i].mx=max(t[i*2].mx,t[i*2+1].mx);
    t[i].mn=min(t[i*2].mn,t[i*2+1].mn);
}
void update(int i,ll v){
    t[i].sum+=v*(t[i].r-t[i].l+1);
    t[i].mx+=v;
    t[i].mn+=v;
    t[i].lazy+=v;
}
void pushdown(int i){
    if(t[i].lazy!=0){
        update(i*2,t[i].lazy);
        update(i*2+1,t[i].lazy);
        t[i].lazy=0;
    }
}
void build(int i,int left,int right){
    t[i].l=left;
    t[i].r=right;
    if(left==right){
        t[i].sum=num[left];
        t[i].mn=num[left];
        t[i].mx=num[left];
        return;
    }
    int mid=(t[i].l+t[i].r)/2;
    build(i*2,left,mid);
    build(i*2+1,mid+1,right);
    pushup(i);
}
void add(int i,int left,int right,ll v){
    if(t[i].l==left&&t[i].r==right){
        update(i,v);
        return;
    }
    pushdown(i);
    int mid=(t[i].l+t[i].r)/2;
    if(mid>=right)add(i*2,left,right,v);
    else if(mid+1<=left)add(i*2+1,left,right,v);
    else{
        add(i*2,left,mid,v);
        add(i*2+1,mid+1,right,v);
    }
    pushup(i);
}
ll qsum(int i,int left,int right){
    if(t[i].l==left&&t[i].r==right){
        return t[i].sum;
    }
    pushdown(i);
    int mid=(t[i].l+t[i].r)/2;
    if(mid>=right)return qsum(i*2,left,right);
    else if(mid+1<=left)return qsum(i*2+1,left,right);
    else return qsum(i*2,left,mid)+qsum(i*2+1,mid+1,right);
}
ll qmax(int i,int left,int right){
    if(t[i].l==left&&t[i].r==right){
        return t[i].mx;
    }
    pushdown(i);
    int mid=(t[i].l+t[i].r)/2;
    if(mid>=right)return qmax(i*2,left,right);
    else if(mid+1<=left)return qmax(i*2+1,left,right);
    else return max(qmax(i*2,left,right),qmax(i*2+1,left,right));
}
ll qmin(int i,int left,int right){
    if(t[i].l==left&&t[i].r==right){
        return t[i].mn;
    }
    pushdown(i);
    int mid=(t[i].l+t[i].r)/2;
    if(mid>=right)return qmin(i*2,left,right);
    else if(mid+1<=left)return qmin(i*2+1,left,right);
    else return min(qmin(i*2,left,right),qmin(i*2+1,left,right));
}
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%lld",&num[i]);
    }
    build(1,1,n);
    for(int i=1;i<=m;i++){
        int t;
        scanf("%d",&t);
        if(t==1){//区间加
            int x,y;
            ll k;
            scanf("%d %d %lld",&x,&y,&k);
            add(1,x,y,k);
        }
        else{//区间求和
            int x,y;
            scanf("%d %d",&x,&y);
            printf("%lld\n",qsum(1,x,y));
        }
    }
    return 0;
}
posted @ 2017-08-01 13:08  玫葵之蝶  阅读(115)  评论(0编辑  收藏  举报