洛谷 P1438 无聊的数列

题目背景

无聊的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 <ctype.h> 
#include <cstdio>
#define N 100005

int n,m;
struct Segment
{
    int l,r,mid,val,flag,gc;
    Segment *ch[2];
    Segment()
    {
        ch[0]=ch[1]=NULL;
        gc=l=r=mid=val=flag=0;
    }
}*root=new Segment;
class segment
{
    public:
        void build(Segment *&k,int l,int r)
        {
            k=new Segment;
            k->l=l;k->r=r;
            if(l==r)
            {
                scanf("%d",&k->val);
                return;
            }
            k->mid=l+r>>1;
            build(k->ch[0],l,k->mid);
            build(k->ch[1],k->mid+1,r);
        }
        void update(Segment *&k,int l,int r,int a,int b,int d)
        {
            if(k->l==l&&k->r==r)
            {
                k->flag+=a+b*(l-d);
                k->gc+=b;
                return;
            }
            if(l>k->mid) update(k->ch[1],l,r,a,b,d);
            else if(r<=k->mid) update(k->ch[0],l,r,a,b,d);
            else update(k->ch[0],l,k->mid,a,b,d),update(k->ch[1],k->mid+1,r,a,b,d);
        }
        int query(Segment *&k,int x,int y)
        {
            if(k->l==k->r) return k->val+k->flag;
            int ans;
            if(x<=k->mid) ans=query(k->ch[0],x,y);
            else ans=query(k->ch[1],x,y);
            ans+=k->flag+k->gc*(y-k->l);
            return ans;
        }
};
class segment *tree;
int Main()
{
    scanf("%d%d",&n,&m);
    tree->build(root,1,n);
    for(int opt,a,b,c,d;m--;)
    {
        scanf("%d",&opt);
        if(opt==1)
        {
            scanf("%d%d%d%d",&a,&b,&c,&d);
            tree->update(root,a,b,c,d,a);
        }
        else 
        {
            scanf("%d",&a);
            printf("%d
",tree->query(root,a,a));
        }
    }
}
int sb=Main();
int main(int argc,char *argv[]) {;}
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
原文地址:https://www.cnblogs.com/ruojisun/p/7395678.html