zoukankan      html  css  js  c++  java
  • P1438 无聊的数列

    区间问题,肯定是线段树了,但是区间加的是一个等差数列,怎么办呢

    我们可以通过差分来维护。

    蛤是差分?

    搞一个数组专门差分,在数组中记录对于l~r的区间加x,在l位置加上x,在r+1位置减去x。

    当查询某个数值时,该位置上的数加上差分数组中1~该位置的前缀和,自己出组数试一下发现这样是对的

    我们线段树刚好可以区间修改和区间求和,所以这题要用到线段树维护差分

    对于首项,我们在线段树的l位置直接加首项,在l+1~r位置区间修改,每个位置加上d,在r+1位置减去等差数组中

    的最后一项也就是a1+(r-l)d,这样我们的区间加等差数列就维护好了。

    单点查询时,查询线段树中1~l的值加上原数组中a[l]的值。

    然后特别注意的是r+1>n的情况我们不必再修改,会RE

    对于l+1>r的情况,只需在l位置加上首项,l+1位置减去首项。

    #include<iostream>
    #include<cstdio>
    #define lson k<<1,l,mid
    #define rson k<<1|1,mid+1,r
    #define ls k<<1
    #define rs k<<1|1
    #define sum(rt) tr[rt].sum
    #define laz(rt) tr[rt].laz
    #define mid ((l+r)>>1)
    using namespace std;
    const int maxn=100005;
    int n,m,a[maxn];
    struct node{
        int sum,laz;
    }tr[maxn<<2];
    inline int read(){
        int s=0,w=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
        return s*w;
    }
    inline void update(int k){
        sum(k)=sum(ls)+sum(rs);
    }
    inline void down(int k,int l,int r){
        sum(ls)+=laz(k)*(mid-l+1);
        laz(ls)+=laz(k);
        sum(rs)+=laz(k)*(r-mid);
        laz(rs)+=laz(k);
        laz(k)=0;
    }
    void change(int k,int l,int r,int x,int y,int val){
        if(x<=l&&y>=r){
            sum(k)+=val*(r-l+1);
            laz(k)+=val;
            return ;
        }
        if(laz(k)!=0)down(k,l,r);
        if(x<=mid)change(lson,x,y,val);
        if(y>mid)change(rson,x,y,val);
        update(k);
    }
    int ask(int k,int l,int r,int x,int y){
        if(l==x&&y==r){
            return sum(k);
        }
        if(laz(k)!=0)down(k,l,r);
        if(y<=mid)return ask(lson,x,y);
        else if(x>mid)return ask(rson,x,y);
        else return ask(lson,x,mid)+ask(rson,mid+1,y);
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<=n;++i)
            a[i]=read();
        int opt,l,r,k,d;
        while(m--){
            opt=read();
            if(opt==1){
                l=read();r=read();k=read();d=read();
                change(1,1,n,l,l,k);
                if(l!=r)change(1,1,n,l+1,r,d);
                if(r+1<=n)change(1,1,n,r+1,r+1,-(k+(r-l)*d));
            }
            else {
                l=read();
                printf("%d
    ",ask(1,1,n,1,l)+a[l]);
            }
        }
        return 0;
    }
  • 相关阅读:
    The hardest problem ever
    1146 Topological Order
    1147 Heaps
    Weekly Contest 184
    1148 Werewolf
    1149 Dangerous Goods Packaging
    1150 Travelling Salesman Problem
    1151 LCA in a Binary Tree (30point(s))
    1152 Google Recruitment
    美团2020春招笔试
  • 原文地址:https://www.cnblogs.com/sanjinliushi/p/11567445.html
Copyright © 2011-2022 走看看