[luogu 3372][模板]线段树1{线段树or分块}

版权声明:请大家斧正,如喜欢的话,为拙见点一个赞吧。 https://blog.csdn.net/qq_39897867/article/details/82814832

题目

https://www.luogu.org/problemnew/show/P3372


解题思路

一道模板题,温习~~~


代码(SegmentTree)

#include<cstdio>
using namespace std; 
struct SegmentTree{
	int l,r; 
	long long sum,add; 
	#define l(x) tree[x].l 
	#define r(x) tree[x].r 
	#define sum(x) tree[x].sum
	#define add(x) tree[x].add
}tree[100010*4];
int n,m,a[100010]; 
void build(int p,int l,int r)
{
	l(p)=l,r(p)=r; 
	if (l==r) {sum(p)=a[l]; return;}
	int mid=(l+r)/2; 
	build(p*2,l,mid); 
	build(p*2+1,mid+1,r); 
	sum(p)=sum(p*2)+sum(p*2+1); 
}
void spread(int p)
{
	if (add(p)) {
		sum(p*2)+=add(p)*(r(p*2)-l(p*2)+1); 
		sum(p*2+1)+=add(p)*(r(p*2+1)-l(p*2+1)+1); 
		add(p*2)+=add(p); 
		add(p*2+1)+=add(p); 
		add(p)=0; 
	}
}
void change(int p,int l,int r,int d)
{
	if (l<=l(p)&&r>=r(p)){
		sum(p)+=(long long)d*(r(p)-l(p)+1); 
		add(p)+=d; 
		return; 
	}
	spread(p); 
	int mid=(l(p)+r(p))/2; 
	if (l<=mid) change(p*2,l,r,d);
	if (r>mid) change(p*2+1,l,r,d); 
	sum(p)=sum(p*2)+sum(p*2+1); 
}
long long ask(int p,int l,int r)
{
	if (l<=l(p)&&r>=r(p)) return sum(p); 
	spread(p); 
	int mid=(l(p)+r(p))/2; 
	long long val=0; 
	if (l<=mid) val+=ask(p*2,l,r); 
	if (r>mid) val+=ask(p*2+1,l,r); 
	return val; 
}
int main()
{
	scanf("%d%d",&n,&m); 
	for (int i=1;i<=n;i++) scanf("%d",&a[i]); 
	build(1,1,n); 
	while (m--){
		char op[2]; int l,r,d; 
		scanf("%s%d%d",op,&l,&r); 
		if (op[0]=='1') {
			scanf("%d",&d); 
			change(1,l,r,d); 
		} else printf("%lld\n",ask(1,l,r));  
	}
}

代码(分块)

#include<cstdio>
#include<cmath>
#define ll long long 
using namespace std; 
ll a[100010],sum[100010],add[100010]; 
int L[100010],R[100010]; 
int pos[100010]; 
int n,m,t; 
void change(int l,int r,ll d)
{
    int p=pos[l],q=pos[r]; 
    if (p==q){
        for (int i=l;i<=r;i++) a[i]+=d; 
        sum[p]+=d*(r-l+1); 
    } else {
        for (int i=p+1;i<=q-1;i++) add[i]+=d; 
        for (int i=l;i<=R[p];i++) a[i]+=d; 
        sum[p]+=d*(R[p]-l+1); 
        for (int i=L[q];i<=r;i++) a[i]+=d; 
        sum[q]+=d*(r-L[q]+1); 
    }
}
ll ask(int l,int r)
{
    int p=pos[l],q=pos[r]; 
    ll ans=0; 
    if (p==q) {
        for (int i=l;i<=r;i++) ans+=a[i]; 
        ans+=add[p]*(r-l+1); 
    } else {
        for (int i=p+1;i<=q-1;i++) 
         ans+=sum[i]+add[i]*(R[i]-L[i]+1); 
        for (int i=l;i<=R[p];i++) ans+=a[i]; 
        ans+=add[p]*(R[p]-l+1); 
        for (int i=L[q];i<=r;i++) ans+=a[i]; 
        ans+=add[q]*(r-L[q]+1); 
    }
    return ans; 
}
int main()
{
    scanf("%d%d",&n,&m); 
    for (int i=1;i<=n;i++) scanf("%lld",&a[i]); 
    t=(int)sqrt((double)n); 
    for (int i=1;i<=t;i++){
        L[i]=(i-1)*t+1; 
        R[i]=i*t; 
    }
    if (R[t]<n) t++,L[t]=R[t-1]+1,R[t]=n; 
    for (int i=1;i<=t;i++)
     for (int j=L[i];j<=R[i];j++){
     	pos[j]=i; sum[i]+=a[j]; 
     }
    while (m--){
        char op[3]; 
        int l,r,d; 
        scanf("%s%d%d",op,&l,&r); 
        if (op[0]=='1'){
            scanf("%d",&d); 
            change(l,r,d); 
        } else printf("%lld\n",ask(l,r)); 
    }
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/82814832