线段树模板合集

区间加一个数,区间求和(带懒标记)

题目链接:[https://www.luogu.com.cn/problem/P3372]

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ull unsigned long long
#define ll long long
#define INF 0x3f3f3f3f
#define N 400010
#define lson rt<<1
#define rson rt<<1|1
#define mo 80112002
#define lowbit(x) (x)&(-(x))
void FRE(){freopen("subsets.in","r",stdin);freopen("subsets.out","w",stdout);}
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ll)(ch-'0');ch=getchar();}
    return x*f;
}

ll sum[N],add[N];
int n,Q;
void pushup(int rt)
{
	sum[rt]=sum[lson] + sum[rson];
}
void build(int rt , int l ,int r)
{
	add[rt] = 0;
	if (l == r)
	{
		sum[rt]=read();
		return ;
	}
	int mid=(l + r)>>1;
	build(lson,l,mid);
	build(rson,mid+1,r);
	pushup(rt);
	return ;
}

void pushdown(int rt,int l,int r)
{
	if (add[rt])
	{
		add[lson]+=add[rt];
		add[rson]+=add[rt];
		int mid=(l+r)>>1;
		sum[lson]+=add[rt]*(mid-l+1);
		sum[rson]+=add[rt]*(r-mid);
		add[rt]=0;
	}
	return ;
}
void modify(int rt,int l,int r,int x,int y,int val)
{
	if (x<=l && y>=r)
	{
		add[rt]+=val;
		sum[rt]+=val*(r-l+1);
		return ;
	}
	pushdown(rt,l,r);
	int mid=(l+r)>>1;
	if (x<=mid) modify(lson,l,mid,x,y,val);
	if (mid<y) modify(rson,mid+1,r,x,y,val);
	pushup(rt);
	return ;
}
ll query(int rt , int l , int r ,int x , int y)
{
	if (x<=l && r<=y) return sum[rt];
	pushdown(rt,l,r);
	int mid=(l+r)>>1;
	ll res=0;
	if (x<=mid) res+=query(lson,l,mid,x,y);
	if (mid<y) res+=query(rson, mid+1,r,x,y);
	return res;
}
int main()
{
	n=read();Q=read();
	build(1,1,n);
	while (Q--)
	{
		int ty=read(),x=read(),y=read();
		if (ty==1)
		{
			int k=read();
			modify(1,1,n,x,y,k);
		}
		else
		{
			printf("%lld\n",query(1,1,n,x,y));
		}
		
	}
}

区间开平方

题目链接:[https://www.luogu.com.cn/problem/P4145]

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define inf 1e18
#define ll long long
#define N 1000010
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,m;
ll mx[N],mn[N],sum[N],tag[N];
void pushup(int rt)
{
	sum[rt]=sum[lson]+sum[rson];
	mx[rt]=max(mx[lson],mx[rson]);
	mn[rt]=min(mn[lson],mn[rson]);
}
void pushdown(int rt,int l,int r)
{
	if (!tag[rt]) return ;
	int mid=(l+r)>>1;
	tag[lson]+=tag[rt],tag[rson]+=tag[rt];
	sum[lson]+=1LL*(mid-l+1)*tag[rt];
	sum[rson]+=1LL*(r-mid)*tag[rt];
	mx[lson]+=tag[rt],mx[rson]+=tag[rt];
	mn[lson]+=tag[rt],mn[rson]+=tag[rt];
	tag[rt]=0;
}
void build(int rt,int l,int r)
{
	if (l==r) {mx[rt]=mn[rt]=sum[rt]=read();return ;}
	int mid=(l+r)>>1;
	build (lson,l,mid),build(rson,mid+1,r);
	pushup(rt);
}
bool check(int rt)
{
	return (mx[rt]==mn[rt]||(mx[rt]-mn[rt]==floor(sqrt(mx[rt]))-floor(sqrt(mn[rt]))));
}
void modify(int rt,int l,int r,int x,int y)
{
	if (x<=l&&r<=y&&check(rt))
	{
		ll val=floor(sqrt(mx[rt]))-mx[rt];
		tag[rt]+=val;sum[rt]+=(r-l+1)*val;
		mn[rt]+=val;mx[rt]+=val;
		return ;
	}
	int mid=(l+r)>>1;
	if (tag[rt]) pushdown(rt,l,r);
	if (x<=mid) modify(lson,l,mid,x,y);
	if (y>mid) modify(rson,mid+1,r,x,y);
	pushup(rt);
}
ll query(int rt,int l,int r,int x,int y)
{
	if (x<=l&&r<=y) return sum[rt];
	pushdown(rt,l,r);
	int mid=(l+r)>>1;ll res=0;
	if (x<=mid) res+=query(lson,l,mid,x,y);
	if (y>mid) res+=query(rson,mid+1,r,x,y);
	return res;
}
int main()
{
	n=read();
	build(1,1,n); 
	int m=read();
	while (m--)
	{
		int ty=read(),x=read(),y=read();
		if (x>y) swap(x,y);
		if (!ty) modify(1,1,n,x,y);
		else printf("%lld\n",query(1,1,n,x,y));
	}
	return 0;
}

看了下题解,好像大家都打的更简短些,建议直接看题解

区间求max,min:

其实就把第一个的pushup和sum改一下就行。

区间替换:

把区间加减的“+=val”改成“=val”就行。

posted @ 2020-11-01 08:41  蛙蛙1551  阅读(110)  评论(0编辑  收藏  举报