几种线段树举例

我做过的几种线段树类型,贴一下代码备忘


1.HDU1166 更新节点,区间求和

#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
using namespace std;

#define MAXN 100005
struct node
{
	int begin,end;
	int value;
};

node ST[MAXN*2];
int N,A[MAXN];

int initST(int cur,int begin,int end)
{
	int mid=(begin+end)/2;
	ST[cur].begin=begin;
	ST[cur].end=end;
	if(begin==end)
	{
		return ST[cur].value=A[begin];
	}else
	{
		return ST[cur].value=initST(cur<<1,begin,mid)+initST(cur<<1|1,mid+1,end);
	}
}

int Query(int cur,int a,int b)
{
	int mid=(ST[cur].begin+ST[cur].end)/2;
	if(a==ST[cur].begin && b==ST[cur].end)
	{
		return ST[cur].value;
	}
	if(a>mid)
		return Query(cur<<1|1,a,b);
	if(b<=mid)
		return Query(cur<<1,a,b);
	return Query(cur<<1,a,mid)+Query(cur<<1|1,mid+1,b);
}

void Add(int cur,int pos,int num)
{
	ST[cur].value+=num;
	if(ST[cur].begin==ST[cur].end)
		return;
	if(pos<=(ST[cur].begin+ST[cur].end)/2)
		Add(cur<<1,pos,num);
	else
		Add(cur<<1|1,pos,num);
}
void Sub(int cur,int pos,int num)
{
	ST[cur].value-=num;
	if(ST[cur].begin==ST[cur].end)
		return;
	if(pos<=(ST[cur].begin+ST[cur].end)/2)
		Sub(cur<<1,pos,num);
	else
		Sub(cur<<1|1,pos,num);
}
int main()
{
	int n,i,j,a,b;
	string s;
	cin>>n;
	for(i=0;i<n;++i)
	{
		cin>>N;
		memset(ST,0,sizeof(ST));
		for(j=0;j<N;++j)
		{
			cin>>A[j];
		}
		initST(1,0,N-1);
		cout<<"Case "<<i+1<<":"<<endl;
		while(cin>>s,s!="End")
		{
			if(s=="Query")
			{
				cin>>a>>b;
				cout<<Query(1,a-1,b-1)<<endl;
			}else if(s=="Add")
			{
				cin>>a>>b;
				Add(1,a-1,b);
			}else if(s=="Sub")
			{
				cin>>a>>b;
				Sub(1,a-1,b);
			}
		}
	}
	
}

2.HDU1754 更新节点,区间最值

#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
using namespace std;

#define MAXN 200900
struct node
{
	int begin,end;
	int value;
};

int Max(const int &a,const int &b)
{
	return a>b?a:b;
}

node ST[MAXN*3];
int N,A[MAXN];

int initST(int cur,int begin,int end)
{
	int mid=(begin+end)/2;
	ST[cur].begin=begin;
	ST[cur].end=end;
	if(begin==end)
	{
		return ST[cur].value=A[begin];
	}else
	{
		return ST[cur].value=Max(initST(cur<<1,begin,mid),initST(cur<<1|1,mid+1,end));
	}
}

int Query(int cur,int a,int b)
{
	int mid=(ST[cur].begin+ST[cur].end)/2;
	if(a==ST[cur].begin && b==ST[cur].end)
	{
		return ST[cur].value;
	}
	if(a>mid)
		return Query(cur<<1|1,a,b);
	if(b<=mid)
		return Query(cur<<1,a,b);
	return Max(Query(cur<<1,a,mid),Query(cur<<1|1,mid+1,b));
}

int Update(int cur,int pos,int num)
{
	if(ST[cur].begin==ST[cur].end)
	{
		ST[cur].value=num;
		return num;
	}
	if(pos<=(ST[cur].begin+ST[cur].end)/2)
	{
		int r=Update(cur<<1,pos,num);
		ST[cur].value=Max(r,ST[cur<<1|1].value);
		return ST[cur].value;
	}
	else
	{
		int r=Update(cur<<1|1,pos,num);
		ST[cur].value=Max(r,ST[cur<<1].value);
		return ST[cur].value;
	}
}

int main()
{
	int n,i,j,a,b,M;
	char c;
	while(cin>>N>>M)
	{
		memset(ST,0,sizeof(ST));
		for(j=0;j<N;++j)
		{
			scanf("%d",A+j);
		}
		initST(1,0,N-1);

		for(j=0;j<M;++j)
		{
			scanf("%*[ \n]%c%d%d",&c,&a,&b);
			if(c=='Q')
			{
				printf("%d\n",Query(1,a-1,b-1));
			}else
			{
				Update(1,a-1,b);
			}
		}
	}
	
}


3.HDU1698 成段更新

#include <cstdio>
#include <iostream>

using namespace std;

#define MAXN 200005
#define LL(x) ((x)<<1)
#define RR(x) ((x)<<1|1)
struct node
{
	int begin,end;
	int value;
};

node ST[MAXN*2+1];
int N,A[MAXN];
int Q;

void initST(int cur,int begin,int end)
{
	int mid=(begin+end)/2;
	ST[cur].begin=begin;
	ST[cur].end=end;
	//ST[cur].value=1;
	if(begin==end)
	{
		return;
	}
	initST(cur<<1,begin,mid);
	initST(cur<<1|1,mid+1,end);
}


void Update(int cur,int begin,int end,int value)
{
	if (ST[cur].begin>end || ST[cur].end<begin)
	{
		return ;
	}
	if(begin<=ST[cur].begin && ST[cur].end<=end)
	{
		ST[cur].value=value;
		return;
	}
	if(ST[cur].value==value)
		return;
	if(ST[cur].value!=-1)
		ST[LL(cur)].value=ST[RR(cur)].value=ST[cur].value;
	ST[cur].value=-1;
	Update(LL(cur),begin,end,value);
	Update(RR(cur),begin,end,value);

}

int Query(int cur,int begin,int end)
{
	if (ST[cur].begin>end || ST[cur].end<begin)
	{
		return 0;
	}
	if (ST[cur].value == -1)
	{
		return Query(LL(cur),begin,end)+Query(RR(cur),begin,end);
	}
	int maxleft=begin>ST[cur].begin?begin:ST[cur].begin;
	int minright=end<ST[cur].end?end:ST[cur].end;
	return ST[cur].value*(minright-maxleft+1);
}

void print()
{
	int i,j=0,index=1;
	for (i=1;i<=N;i*=2)
	{
		for (j=0;j<i;++j)
		{
			cout<<ST[index++].value<<" ";
		}
		cout<<endl;
	}
}

int solve()
{
	int a,b,v,j;
	scanf("%d%d",&N,&Q);
	initST(1,0,N-1);
	ST[1].value=1;
	for(j=0;j<Q;++j)
	{
		scanf("%d%d%d",&a,&b,&v);
		Update(1,a-1,b-1,v);
		//print();
	}
	return Query(1,0,N-1);
}

int main()
{
	int n,i;
	scanf("%d",&n);
	for(i=0;i<n;++i)
	{
		cout<<"Case "<<i+1<<": The total value of the hook is "<<solve()<<"."<<endl;
	}
	return 0;
}


4.HDU1394 更新节点求区间和


#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
using namespace std;

#define MAXN 10000
struct node
{
	int begin,end;
	int value;
};

node ST[MAXN*2];
int N,A[MAXN],B[MAXN];

int initST(int cur,int begin,int end)
{
	int mid=(begin+end)>>1;
	ST[cur].begin=begin;
	ST[cur].end=end;
	if(begin==end)
	{
		return ST[cur].value=A[begin];
	}else
	{
		return ST[cur].value=initST(cur<<1,begin,mid)+initST(cur<<1|1,mid+1,end);
	}
}

int Query(int cur,int a,int b)
{
	int mid=(ST[cur].begin+ST[cur].end)>>1;
	if(a==ST[cur].begin && b==ST[cur].end)
	{
		return ST[cur].value;
	}
	if(a>mid)
		return Query(cur<<1|1,a,b);
	if(b<=mid)
		return Query(cur<<1,a,b);
	return Query(cur<<1,a,mid)+Query(cur<<1|1,mid+1,b);
}

void Add(int cur,int pos,int num)
{
	ST[cur].value+=num;
	if(ST[cur].begin==ST[cur].end)
		return;
	if(pos<=((ST[cur].begin+ST[cur].end)>>1))
		Add(cur<<1,pos,num);
	else
		Add(cur<<1|1,pos,num);
}
void Sub(int cur,int pos,int num)
{
	ST[cur].value-=num;
	if(ST[cur].begin==ST[cur].end)
		return;
	if(pos<=((ST[cur].begin+ST[cur].end)>>1))
		Sub(cur<<1,pos,num);
	else
		Sub(cur<<1|1,pos,num);
}
int main()
{
	int n,i,j,a,b;
	string s;
	
	while(cin>>N)
	{
		
		memset(ST,0,sizeof(ST));
		//memset(A,0,sizeof(A));
		initST(1,0,N-1);
		int sum=0;
		for(j=0;j<N;++j)
		{
			int num;
			//cin>>num;
			scanf("%d",&num);
			B[j]=num;
			Add(1,num,1);
			if(num<N-1) sum+=Query(1,num+1,N-1);
		}
		int minn=sum;
		for (j=0;j<N;++j)
		{
			sum=sum+N-B[j]*2-1;
			if (sum<minn)
			{
				minn=sum;
			}
		}
		cout<<minn<<endl;
	}
	
}


5.POJ3468 更新区间,区间求和


#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
using namespace std;


#define MAXN 100005
struct node
{
	int begin,end;
	__int64 value;
	__int64 add;
};

node ST[MAXN*4];
int N,A[MAXN],Q;

__int64 initST(int cur,int begin,int end)
{
	int mid=(begin+end)>>1;
	ST[cur].begin=begin;
	ST[cur].end=end;
	if(begin==end)
	{
		return ST[cur].value=A[begin];
	}else
	{
		return ST[cur].value=initST(cur<<1,begin,mid)+initST(cur<<1|1,mid+1,end);
	}
}

__int64 Query(int cur,int pos1,int pos2)
{
	int mid=(ST[cur].begin+ST[cur].end)>>1;
	if(pos1<=ST[cur].begin && ST[cur].end<=pos2)
	{
		return ST[cur].value+ST[cur].add*(ST[cur].end-ST[cur].begin+1);
	}
	
	if (ST[cur].add)
	{
		ST[cur].value+=ST[cur].add*(ST[cur].end-ST[cur].begin+1);
		ST[cur<<1].add+=ST[cur].add;
		ST[cur<<1|1].add+=ST[cur].add;
		ST[cur].add=0;
	}
	if(pos1>mid)
		return Query(cur<<1|1,pos1,pos2);
	if(pos2<=mid)
		return Query(cur<<1,pos1,pos2);
	return Query(cur<<1,pos1,mid)+Query(cur<<1|1,mid+1,pos2);
}

void print()
{
	int i,j;
	int k=1;
	for(i=1;i<=N;i*=2)
	{
		for (j=0;j<i;++j)
		{
			printf(" %d(%d)",ST[k].value,ST[k].add);
			k++;
		}
		printf("\n");
	}
}

void Add(int cur,int pos1,int pos2,int num)
{
	if(pos1<=ST[cur].begin && ST[cur].end<=pos2)
	{
		//ST[cur].value+=num*(ST[cur].end-ST[cur].begin+1);
		ST[cur].add+=num;
		return;
	}
	if (ST[cur].add)
	{
		ST[cur].value+=ST[cur].add*(ST[cur].end-ST[cur].begin+1);
		ST[cur<<1].add+=ST[cur].add;
		ST[cur<<1|1].add+=ST[cur].add;
		ST[cur].add=0;
	}
	int a=((pos1>ST[cur].begin)?pos1:ST[cur].begin);
	int b=((ST[cur].end<pos2)?ST[cur].end:pos2);
	ST[cur].value+=num*(b-a+1);
	int mid=(ST[cur].begin+ST[cur].end)>>1;
	if (pos2>mid)
		Add(cur<<1|1,pos1,pos2,num);
	if (pos1<=mid)
		Add(cur<<1,pos1,pos2,num);
	
	
	
}

int main()
{
	int n,i,a,b,c;
	char s;
	
	scanf("%d%d",&N,&Q);
	
	for(i=0;i<N;++i)
	{
		scanf("%d",A+i);
	}
	initST(1,0,N-1);

	for (i=0;i<Q;++i)
	{
		scanf("%*[ \n]%c",&s);
		if(s=='Q')
		{
			scanf("%d%d",&a,&b);
			printf("%I64d\n",Query(1,a-1,b-1));
		}else
		{
			scanf("%d%d%d",&a,&b,&c);
			Add(1,a-1,b-1,c);
		}
		//print();
	}
	
	
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值