zoukankan      html  css  js  c++  java
  • 线段树模板合集

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

    题目链接:[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
    ",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
    ",query(1,1,n,x,y));
    	}
    	return 0;
    }
    

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

    区间求max,min:

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

    区间替换:

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

  • 相关阅读:
    uva 11248 最大流 ISAP
    【力扣】133. 克隆图
    【力扣】125. 验证回文串
    【力扣】130. 被围绕的区域
    【力扣】337. 打家劫舍 III
    【力扣】104. 二叉树的最大深度-及二叉树的遍历方式
    【力扣】392. 判断子序列
    【力扣】95. 不同的二叉搜索树 II
    【力扣】120. 三角形最小路径和
    【力扣】两个数组的交集 II
  • 原文地址:https://www.cnblogs.com/71-111/p/13908171.html
Copyright © 2011-2022 走看看