您的位置:首页 > 其它

ANSI C 线段树模板

2017-12-31 14:21 295 查看
线段树维护区间+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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: