[洛谷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

分析一下题意:给出一个长度为n的序列,m次操作,单点修改和区间修改,单点查询.

做法:

  • 差分记录修改
  • 线段树维护区间
  • 查询时输出修改的值加原值

下面贴一下代码:

#include<bits/stdc++.h>
#define ll(x) (x<<1)
#define rr(x) (x<<1|1)
using namespace std;
const int N=100000+5;

int n, m, w[N];

struct segment_tree{
    int l, r, sum, tag;
}t[N*4];

int gi(){
    int ans = 0 , f = 1; char i = getchar();
    while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();}
    while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();}
    return ans * f;
}

void up(int x){
    t[x].sum = t[ll(x)].sum+t[rr(x)].sum;
}

void build(int node,int l,int r){
    t[node].l = l; t[node].r = r;
    if(l == r) return;
    int mid = (l+r>>1);
    build(ll(node),l,mid);
    build(rr(node),mid+1,r);
    up(node);
}

void pushdown(int node){
    int ls = ll(node), rs = rr(node), tag = t[node].tag;
    int l = t[node].l, r = t[node].r , mid = (l+r>>1);
    t[ls].tag += tag; t[rs].tag += tag;
    t[ls].sum += tag*(mid-l+1); t[rs].sum += tag*(r-mid);
    t[node].tag = 0;
}

void updata(int node,int l,int r,int val){
    if(l <= t[node].l && t[node].r <= r){
    t[node].tag += val;
    t[node].sum += val*(t[node].r-t[node].l+1);
    return;
    }
    if(t[node].tag) pushdown(node);
    int mid = (t[node].l+t[node].r>>1);
    if(l <= mid) updata(ll(node),l,r,val);
    if(mid < r) updata(rr(node),l,r,val);
    up(node);
}

int query(int node,int l,int r){
    if(l <= t[node].l && t[node].r <= r) return t[node].sum;
    if(r < t[node].l || t[node].r < l) return 0;
    if(t[node].tag) pushdown(node);
    return query(ll(node),l,r)+query(rr(node),l,r);
}

int main(){
    //freopen("data.in","r",stdin);
    int flag, l, r, k, d; n = gi(); m = gi();
    for(int i=1;i<=n;i++) w[i] = gi();
    build(1,1,n);
    while(m--){
    flag = gi(); l = gi();
    if(flag == 1){
        r = gi(); k = gi(); d = gi();
        updata(1,l+1,r,d); updata(1,l,l,k);
        if(r+1 <= n) updata(1,r+1,r+1,-d*(r-l)-k);//因为建树的时候没有建n+1的下标,所以特判防越界
    }
    else printf("%d\n",w[l]+query(1,1,l));
    }
    return 0;
}
posted @ 2018-04-17 16:39  Brave_Cattle  阅读(203)  评论(0编辑  收藏  举报