ANSI C 线段树模板

线段树维护区间+x,区间查询区间和。Coded under gcc。

SEGT.cpp

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int maxn=1000000+10;
namespace segT{
    int lch[maxn],rch[maxn],lst[maxn],rst[maxn];
    int sum[maxn],lazy[maxn],ncnt=0,a[maxn/4];
    void build(int t,int ls,int rs){
        if(ls==rs){
            lch[t]=rch[t]=0;lst[t]=rst[t]=ls;
            sum[t]=a[ls];lazy[t]=0;
        }else{
            int mid=(ls+rs)/2,nl=++ncnt,nr=++ncnt;
            build(nl,ls,mid);build(nr,mid+1,rs);
            lch[t]=nl;rch[t]=nr;
            lst[t]=ls;rst[t]=rs;
            sum[t]=sum[nl]+sum[nr];
            lazy[t]=0;
        }
    }
    int query(int t,int ls,int rs){
        if(lst[t]>rs || rst[t]<ls)return 0;
        if(ls<=lst[t]&&rst[t]<=rs)return sum[t];
        int nl=lch[t],nr=rch[t];
        if(lazy[t]!=0){
            lazy[nl]+=lazy[t];lazy[nr]+=lazy[t];
            sum[nl]+=(rst[nl]-lst[nl]+1)*lazy[t];
            sum[nr]+=(rst[nr]-lst[nr]+1)*lazy[t];
            lazy[t]=0;
        }
        return query(nl,ls,rs)+query(nr,ls,rs);
    }
    void segadd(int t,int ls,int rs,int v){
        if(lst[t]>rs || rst[t]<ls)return;
        if(ls<=lst[t]&&rst[t]<=rs){
            lazy[t]+=v;
            sum[t]+=(rst[t]-lst[t]+1)*v;
            return;
        }
        int nl=lch[t],nr=rch[t];
        if(lazy[t]!=0){
            lazy[nl]+=lazy[t];lazy[nr]+=lazy[t];
            sum[nl]+=(rst[nl]-lst[nl]+1)*lazy[t];
            sum[nr]+=(rst[nr]-lst[nr]+1)*lazy[t];
            lazy[t]=0;
        }
        segadd(nl,ls,rs,v);segadd(nr,ls,rs,v);
        sum[t]=sum[nl]+sum[nr];//maintain !!!!
    }
    void debugT(){
        for(int i=1;i<=ncnt;i++){
            printf("[%3d] %5d %5d %5d %5d %5d\n"
            ,i,lch[i],rch[i],lst[i],rst[i],sum[i]);
        }
    }
}
int main(){
    int n,q;scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)scanf("%d",&segT::a[i]);
    int root=++segT::ncnt;segT::build(root,1,n);
    for(int i=1;i<=q;i++){
        int op;scanf("%d",&op);
        if(op==1){
            int l,r;scanf("%d%d",&l,&r);
            printf("%d\n",segT::query(root,l,r));
        }else if(op==2){
            int l,r,v;scanf("%d%d%d",&l,&r,&v);
            segT::segadd(root,l,r,v);
        }
    }
    return 0;
}

bforce.cpp 暴力程序

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int a[10000+10];
int sum(int l,int r){
    int ans=0;
    for(int i=l;i<=r;i++)
        ans+=a[i];
    return ans;
}
int add(int l,int r,int v){
    for(int i=l;i<=r;i++)
        a[i]+=v;
}
int main(){
    int n,q;scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=q;i++){
        int op;scanf("%d",&op);
        if(op==1){
            int l,r;scanf("%d%d",&l,&r);
            printf("%d\n",sum(l,r));
        }else if(op==2){
            int l,r,v;scanf("%d%d%d",&l,&r,&v);
            add(l,r,v);
        }
    }
    return 0;
}

data.cpp 数据生成器

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
#include<ctime>
int rand(int L,int R){return rand()%(R-L+1)+L;}
int main(){
    srand(time(NULL));
    int n=rand(1000,3000),q=rand(1000,3000);
    printf("%d %d\n",n,q);
    for(int i=1;i<=n;i++)printf("%d ",rand(1,100));
    putchar('\n');
    for(int i=1;i<=q;i++){
        int op=rand(1,2);printf("%d ",op);
        if(op==1){
            int l=rand(1,n),r=rand(l,n);
            printf("%d %d\n",l,r);
        }else{
            int l=rand(1,n),r=rand(l,n),v=rand(-10,10);
            printf("%d %d %d\n",l,r,v);
        }
    }
    return 0;
}

try.bat 对拍程序

@echo off
set /a i=1
:begin
if %i% GTR 100 goto end
  data.exe   > input.txt
  SEGT.exe   < input.txt > output.txt
  bforce.exe < input.txt > std.txt
  fc std.txt output.txt
  if errorlevel 1 pause
  set /a i=i+1
goto begin
:end
echo [end]
pause
阅读更多
版权声明:文章纯属版主手敲,请同学们尊重版主的知识产权。 https://blog.csdn.net/GGN_2015/article/details/78941746
文章标签: gcc 模板 线段树
个人分类: 数据结构
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭