动态开点线段树 区间加,区间赋值,区间询问

个人感觉,动态开点线段树,就是在普通线段树上套一个开点操作。(就是把原来的#define中的lson和rson,换一下即可)

区间加,区间询问
#include 
#define int long long
using namespace std;
const int N=1e5+5;
int n,m,x,y,v,now,cnt;
int a[N],add[N*50],sum[N*50],lson[N*50],rson[N*50];

inline void pushdown(int k,int l,int r,int mid)
{
	if (add[k])
	{
		add[lson[k]]+=add[k];
		sum[lson[k]]+=(mid-l+1)*add[k];
		add[rson[k]]+=add[k];
		sum[rson[k]]+=(r-(mid+1)+1)*add[k];
		add[k]=0;
	}
}

void build(int k,int l,int r)
{
	if (l==r) {sum[k]=a[l]; return;}
	if (!lson[k]) lson[k]=++cnt;
	if (!rson[k]) rson[k]=++cnt; 
	int mid=l+r>>1;
	build(lson[k],l,mid);
	build(rson[k],mid+1,r);
	sum[k]=sum[lson[k]]+sum[rson[k]]; 
}

void change(int k,int l,int r,int qx,int qy,int v)
{
	if (qx<=l && r<=qy) 
	{
		add[k]+=v;
		sum[k]+=(r-l+1)*v;
		return;
	}
	if (!lson[k]) lson[k]=++cnt;
	if (!rson[k]) rson[k]=++cnt; 
	int mid=l+r>>1;
	pushdown(k,l,r,mid);
	if (qx<=mid) change(lson[k],l,mid,qx,qy,v);
	if (mid<qy) change(rson[k],mid+1,r,qx,qy,v);
	sum[k]=sum[lson[k]]+sum[rson[k]];	
}

int query(int k,int l,int r,int qx,int qy)
{
	if (qx<=l && r<=qy) return sum[k];
	if (!lson[k]) lson[k]=++cnt;
	if (!rson[k]) rson[k]=++cnt; 
	int mid=l+r>>1;
	pushdown(k,l,r,mid);
	int ans=0;
	if (qx<=mid) ans+=query(lson[k],l,mid,qx,qy);
	if (mid<y) ans+=query(rson[k],mid+1,r,qx,qy);
	return ans;
}

signed main(){
	scanf("%lld%lld",&n,&m);
	cnt=1;
	for (register int i=1; i<=n; ++i) scanf("%lld",&a[i]);
	build(1,1,n);
	for (register int i=1; i<=m; ++i)
	{
		scanf("%lld",&now);
		if (now==1) 
		{
			scanf("%lld%lld%lld",&x,&y,&v);
			change(1,1,n,x,y,v);
		}
		else
		{
			scanf("%lld%lld",&x,&y);
			printf("%lld\n",query(1,1,n,x,y));
		}
	}	
return 0;
}
区间赋值,区间询问
#include 
using namespace std;
const int N=3e5+5;
int n,q,cnt,l,r,v;
int sum[N*50],tag[N*50],lson[N*50],rson[N*50];

inline void pushdown(int k,int l,int r,int mid)
{
	if (~tag[k])
	{
		sum[lson[k]]=(mid-l+1)*tag[k];
		sum[rson[k]]=(r-(mid+1)+1)*tag[k];
		tag[lson[k]]=tag[rson[k]]=tag[k];
		tag[k]=-1;
	}
}

void change(int k,int l,int r,int qx,int qy,int v)
{
	if (qx<=l && r<=qy)
	{ 
		tag[k]=v;
		sum[k]=(r-l+1)*v;
		return;
	}
	if (!lson[k]) lson[k]=++cnt;
	if (!rson[k]) rson[k]=++cnt;
	int mid=l+r>>1;
	pushdown(k,l,r,mid);
	if (qx<=mid) change(lson[k],l,mid,qx,qy,v);
	if (mid<qy) change(rson[k],mid+1,r,qx,qy,v);
	sum[k]=sum[lson[k]]+sum[rson[k]];
}

int main(){
	memset(tag,-1,sizeof(tag));
	scanf("%d",&n);
	scanf("%d",&q);
	cnt=1;
	while (q--)
	{
		scanf("%d%d%d",&l,&r,&v);
		v&=1;
		if (l>r) swap(l,r);
		change(1,1,n,l,r,v);
		printf("%d\n",n-sum[1]);
	}
return 0;
}
推荐一道模板题:区间赋值+区间询问

你可能感兴趣的:(线段树)