P1438 无聊的数列 线段树

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43880084/article/details/102526965

LINK

线段树:

线段树的板子

~好像很久都没写过线段树了的,全忘了不过跟着代码走了一遍感觉还不错 ()不管怎样加油啦

题目背景

无聊的YYB总喜欢搞出一些正常人无法搞出的东西。有一天,无聊的YYB想出了一道无聊的题:无聊的数列。。。(K峰:这题不是傻X题吗)
题目描述

维护一个数列{a[i]},支持两种操作:

1、1 L R K D:给出一个长度等于R-L+1的等差数列,首项为K,公差为D,并将它对应加到a[L]~a[R]的每一个数上。即:令a[L]=a[L]+K,a[L+1]=a[L+1]+K+D,

a[L+2]=a[L+2]+K+2D……a[R]=a[R]+K+(R-L)D。

2、2 P:询问序列的第P个数的值a[P]。
输入格式

第一行两个整数数n,m,表示数列长度和操作个数。

第二行n个整数,第i个数表示a[i](i=1,2,3…,n)。

接下来的m行,表示m个操作,有两种形式:

1 L R K D

2 P 字母意义见描述(L≤R)。
输出格式

对于每个询问,输出答案,每个答案占一行。
输入输出样例
输入 #1

5 2

1 2 3 4 5

1 2 4 1 2

2 3

输出 #1

6

说明/提示

数据规模:

0≤n,m≤100000

|a[i]|,|K|,|D|≤200

Hint:

有没有巧妙的做法?

  • 考虑前缀和
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int sum[N<<2],lazy[N<<2],a[N];
inline void up(int root)
{
	sum[root]=sum[root<<1]+sum[root<<1|1];
}
inline void  pushdown(int root,int len)
{
	if(lazy[root])
	{
		lazy[root<<1]+=lazy[root];
		lazy[root<<1|1]+=lazy[root];
		sum[root<<1]+=lazy[root]*(len-(len>>1));
		sum[root<<1|1]+=lazy[root]*(len>>1);
		lazy[root]=0;
	}
}
void update(int root,int l,int r,int L,int R,int v)
{
	if(l>=L&&r<=R)
	{
		sum[root]+=(r-l+1)*v;
		lazy[root]+=v;return ;
	}
	pushdown(root,r-l+1);int mid=(l+r)>>1;
	if(L<=mid) update(root<<1,l,mid,L,R,v);
	if(R>mid) update(root<<1|1,mid+1,r,L,R,v);
	up(root);
}
int query(int root,int l,int r,int L,int R)
{
	if(l>=L&&r<=R)
	{
		return sum[root];
	}
	int s=0;
	pushdown(root,r-l+1);int mid=(l+r)>>1;
	if(L<=mid) s+=query(root<<1,l,mid,L,R);
	if(R>mid) s+=query(root<<1|1,mid+1,r,L,R);
	return s;
}
int main()
{
	int n,m;scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	while(m--)
	{
		int op,l,r,k,d;scanf("%d",&op);
		if(op==1)
		{
			scanf("%d%d%d%d",&l,&r,&k,&d);
			update(1,1,n,l,l,k);
			if(r>l) update(1,1,n,l+1,r,d);
			update(1,1,n,r+1,r+1,-k-(r-l)*d);
		}else 
		{
			scanf("%d",&k);
			printf("%d\n",query(1,1,n,1,k)+a[k]);
		}
	}
}

板子

#include<iostream>
#include<cstdio>
#define MAXN 1000001
#define ll long long
using namespace std;
unsigned ll n,m,a[MAXN],ans[MAXN<<2],tag[MAXN<<2];
inline ll ls(ll x)
{
    return x<<1;
}
inline ll rs(ll x)
{
    return x<<1|1;
}
void scan()
{
    cin>>n>>m;
    for(ll i=1;i<=n;i++)
    scanf("%lld",&a[i]);
}
inline void push_up(ll p)
{
    ans[p]=ans[ls(p)]+ans[rs(p)];
}
void build(ll p,ll l,ll r)
{
    tag[p]=0;
    if(l==r){ans[p]=a[l];return ;}
    ll mid=(l+r)>>1;
    build(ls(p),l,mid);
    build(rs(p),mid+1,r);
    push_up(p);
} 
inline void f(ll p,ll l,ll r,ll k)
{
    tag[p]=tag[p]+k;
    ans[p]=ans[p]+k*(r-l+1);
}
inline void push_down(ll p,ll l,ll r)
{
    ll mid=(l+r)>>1;
    f(ls(p),l,mid,tag[p]);
    f(rs(p),mid+1,r,tag[p]);
    tag[p]=0;
}
inline void update(ll nl,ll nr,ll l,ll r,ll p,ll k)
{
    if(nl<=l&&r<=nr)
    {
        ans[p]+=k*(r-l+1);
        tag[p]+=k;
        return ;
    }
    push_down(p,l,r);
    ll mid=(l+r)>>1;
    if(nl<=mid)update(nl,nr,l,mid,ls(p),k);
    if(nr>mid) update(nl,nr,mid+1,r,rs(p),k);
    push_up(p);
}
ll query(ll q_x,ll q_y,ll l,ll r,ll p)
{
    ll res=0;
    if(q_x<=l&&r<=q_y)return ans[p];
    ll mid=(l+r)>>1;
    push_down(p,l,r);
    if(q_x<=mid)res+=query(q_x,q_y,l,mid,ls(p));
    if(q_y>mid) res+=query(q_x,q_y,mid+1,r,rs(p));
    return res;
}
int main()
{
    ll a1,b,c,d,e,f;
    scan();
    build(1,1,n);
    while(m--)
    {
        scanf("%lld",&a1);
        switch(a1)
        {
            case 1:{
                scanf("%lld%lld%lld",&b,&c,&d);
                update(b,c,1,n,1,d);
                break;
            }
            case 2:{
                scanf("%lld%lld",&e,&f);
                printf("%lld\n",query(e,f,1,n,1));
                break;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43880084/article/details/102526965