1. 程式人生 > >P1438 無聊的數列(線段樹,差分)

P1438 無聊的數列(線段樹,差分)

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)。

題解:

差分,線段樹

 

const int maxn = 1e6+11;
int sum[maxn],lazy[maxn];

void pushup(int i)
{
    sum[i] = sum[i<<1]+sum[i<<1|1];
}

void pushdown(int i,int l,int r)
{
    int mid = (l+r)>>1;
    if(!lazy[i])return;
    sum[i<<1] += (mid-l+1)*lazy[i];
    sum[i<<1|1] += (r - mid)*lazy[i];
    lazy[i<<1] += lazy[i];
    lazy[i<<1|1] += lazy[i];
    lazy[i] = 0; 
}


void update(int i,int l,int r,int ql,int qr,int v)
{
    if(ql <= l && qr >= r)
    {
        sum[i] += v*(r-l+1);
        lazy[i] += v;
        return; 
    }
    pushdown(i,l,r);
    int mid = (l+r)>>1;
    if(ql<=mid)update(i<<1,l,mid,ql,qr,v);
    if(qr>mid)update(i<<1|1,mid+1,r,ql,qr,v);
    pushup(i);
}

int query(int i,int l,int r,int ql,int qr)
{
    if(ql<=l && qr>=r)return sum[i];
    pushdown(i,l,r);
    int mid = (l+r)>>1;
    int ans = 0;
    if(ql<=mid)ans+=query(i<<1,l,mid,ql,qr);
    if(qr>mid)ans+=query(i<<1|1,mid+1,r,ql,qr);
    return ans;
}

int a[maxn];
int main() 
{
    int n,m;
    cin>>n>>m;
    rep(i,1,n+1)scanf("%d",a+i);
    rep(i,1,m+1)
    { 
        int op,l;scanf("%d%d",&op,&l);
        if(op == 1)
        {
            int r,k,d;
            scanf("%d%d%d",&r,&k,&d);
            update(1,1,n,l,l,k);
            if(r!=n)update(1,1,n,r+1,r+1,-(k+(r-l)*d));
            if(r>l)update(1,1,n,l+1,r,d);     
        }
        else
            printf("%d\n",a[l]+query(1,1,n,1,l));
        
    }
}

 

 

樹狀陣列:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 100010
using namespace std;
int a[MAXN][2],p[MAXN],n;
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int k,int d)
{
    while(x<=n)
    {
        a[x][0]+=k;
        a[x][1]+=d;
        k+=d*lowbit(x);
        x+=lowbit(x);
    }
}
int sum(int x)
{
    int ans=0,pos=x;
    while(pos)
    {
        ans+=a[pos][0]+(x-pos)*a[pos][1];
        pos-=lowbit(pos);
    }
    return ans;
}
int main()
{
    int x,i,l,r,k,d,s,m;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
        scanf("%d",&p[i]);
    for(i=1;i<=m;i++)
    {
        scanf("%d",&s);
        if(s==1)
        {
            scanf("%d%d%d%d",&l,&r,&k,&d);
            add(l,k,d);
            add(r+1,-k-(r-l+1)*d,-d);
        }
        else
        {
            scanf("%d",&x);
            printf("%d\n",p[x]+sum(x));
        }
    }
    return 0;
}