zoukankan      html  css  js  c++  java
  • 计蒜客 31460

    题目链接:https://nanti.jisuanke.com/t/31460

    Ryuji is not a good student, and he doesn't want to study. But there are n books he should learn, each book has its knowledge $a[i]$.

    Unfortunately, the longer he learns, the fewer he gets.

    That means, if he reads books from ll to rr, he will get $a[l] imes L + a[l+1] imes (L-1) + cdots + a[r-1] imes 2 + a[r]$ ($L$ is the length of [ $l$, $r$ ] that equals to $r - l + 1$).

    Now Ryuji has qq questions, you should answer him:

    1. If the question type is 1, you should answer how much knowledge he will get after he reads books [ $l$, $r$ ].

    2. If the question type is 2, Ryuji will change the ith book's knowledge to a new value.

    Input
    First line contains two integers $n$ and $q$ ($n$, $q le 100000$).

    The next line contains n integers represent $a[i]$($a[i] le 1e9$).

    Then in next qq line each line contains three integers $a,b,c$, if $a = 1$, it means question type is $1$, and $b$, $c$ represents [ $l$ , $r$ ].

    If $a = 2$, it means question type is $2$ , and $b$, $c$ means Ryuji changes the bth book' knowledge to $c$.

    Output
    For each question, output one line with one integer represent the answer.

    样例输入

    5 3
    1 2 3 4 5
    1 1 3
    2 5 0
    1 4 5

    样例输出

    10
    8

    题意:

    给出 $n$ 本书编号 $1$ 到 $n$,每本书权值为 $w[i]$,给出 $q$ 个操作,

    操作 $1$,给出区间 $[l,r]$,则区间长度为 $L = r - l + 1$,查询的答案应为 $a[l] imes L + a[l+1] imes (L-1) + cdots + a[r-1] imes 2 + a[r]$,

    操作 $2$,把在编号为 $b$ 的书的权值改成 $c$。

    题解:

    线段树维护两个和:

    一个是普通的区间和 $sumlimits_{i = l}^r {w[i]} = w[l] + cdots + w[r]$;

    另一个是 $sumlimits_{i = l}^r {left[ {w[i] imes left( {n - i + 1} ight)} ight]} = w[l] imes left( {n - l + 1} ight) + cdots + w[r] imes left( {n - r + 1} ight)$。

    那么,对于所有的查询:

    $egin{array}{l}
    Qleft( {l,r} ight) \
    = wleft[ l ight] imes left( {r - l + 1} ight) + wleft[ {l + 1} ight] imes left( {r - l} ight) + cdots + wleft[ r ight] imes 1 \
    = sumlimits_{i = l}^r {left[ {wleft[ i ight] imes left( {r - i + 1} ight)} ight]} \
    = sumlimits_{i = l}^r {left[ {wleft[ i ight] imes left( {n - i + 1 - n + r} ight)} ight]} \
    { m{ = }}sumlimits_{i = l}^r {left[ {wleft[ i ight] imes left( {n - i + 1} ight) - wleft[ i ight] imes left( {n - r} ight)} ight]} \
    = sumlimits_{i = l}^r {left[ {wleft[ i ight] imes left( {n - i + 1} ight)} ight]} - left( {n - r} ight)sumlimits_{i = l}^r {wleft[ i ight]} \
    end{array}$

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    
    int n,q;
    ll a[maxn];
    
    /********************************* Segment Tree - st *********************************/
    struct Node{
        int l,r;
        ll val,sum;
    }node[4*maxn];
    void pushup(int root)
    {
        node[root].val=node[root*2].val+node[root*2+1].val;
        node[root].sum=node[root*2].sum+node[root*2+1].sum;
    }
    void build(int root,int l,int r)
    {
        if(l>r) return;
        node[root].l=l; node[root].r=r;
        node[root].val=0; node[root].sum=0;
        if(l==r)
        {
            node[root].val=a[l];
            node[root].sum=a[l]*(n-l+1);
        }
        else
        {
            int mid=l+(r-l)/2;
            build(root*2,l,mid);
            build(root*2+1,mid+1,r);
            pushup(root);
        }
    }
    void update(int root,int pos,ll val)
    {
        if(node[root].l==node[root].r)
        {
            node[root].val=val;
            node[root].sum=val*(n-pos+1);
            return;
        }
        int mid=node[root].l+(node[root].r-node[root].l)/2;
        if(pos<=mid) update(root*2,pos,val);
        if(pos>mid) update(root*2+1,pos,val);
        pushup(root);
    }
    ll askval(int root,int st,int ed)
    {
        if(st>node[root].r || ed<node[root].l) return 0;
        if(st<=node[root].l && node[root].r<=ed) return node[root].val;
        else return askval(root*2,st,ed)+askval(root*2+1,st,ed);
    }
    ll asksum(int root,int st,int ed)
    {
        if(st>node[root].r || ed<node[root].l) return 0;
        if(st<=node[root].l && node[root].r<=ed) return node[root].sum;
        else return asksum(root*2,st,ed)+asksum(root*2+1,st,ed);
    }
    /********************************* Segment Tree - ed *********************************/
    
    int main()
    {
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        build(1,1,n);
        for(int i=1;i<=q;i++)
        {
            int type;
            scanf("%d",&type);
            if(type==1)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                ll A=asksum(1,a,b);
                ll B=askval(1,a,b);
                //cout<<A<<" "<<B<<endl;
                printf("%lld
    ",A-(n-b)*B);
            }
            else
            {
                int a; ll b;
                scanf("%d%lld",&a,&b);
                update(1,a,b);
            }
        }
    }
  • 相关阅读:
    linux 文件系统(inode和block)
    vue状态管理vuex从浅入深详细讲解
    小白都能看懂的vue中各种通信传值方式,附带详细代码
    CSS3移动端vw+rem不依赖JS实现响应式布局
    JavaScript原生封装ajax请求和Jquery中的ajax请求
    永久解决Sublime包管理package control 打开install package报错 There are no packages available for installation
    从GitLab上创建分支本地拉取项目和提交项目详解
    前端路由的两种实现方式,内附详细代码
    几个例子理解浅拷贝和深拷贝
    讲解JavaScript中对闭包的理解
  • 原文地址:https://www.cnblogs.com/dilthey/p/9619434.html
Copyright © 2011-2022 走看看