zoukankan      html  css  js  c++  java
  • BZOJ-3155-Preprefix sum(线段树/树状数组)

    Description

     

    Input

    第一行给出两个整数N,M。分别表示序列长度和操作个数
    接下来一行有N个数,即给定的序列a1,a2,....an
    接下来M行,每行对应一个操作,格式见题目描述

    Output

    对于每个询问操作,输出一行,表示所询问的SSi的值。

    Sample Input

    5 3
    1 2 3 4 5
    Query 5
    Modify 3 2
    Query 5

    Sample Output

    35
    32

    HINT

    1<=N,M<=100000,且在任意时刻0<=Ai<=100000

    Source

     
     

    题解

    一道数据结构题

    这道题要我们求前缀的前缀和,所以我们就用线段树来维护一下前缀和

    对于修改操作,我们假设原值为x1,修改后的值为x,那么就把区间[i,n]都加上x-x1,把a[i]改成x

    查询操作我就不讲了

    P.s.自己打的快读把左移打成右移,一直RE0.0

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define N 100005 
     4 using namespace std;
     5 int n,m,p,x;
     6 int a[N];
     7 ll sum[N];
     8 ll tree[4*N],mark[4*N];
     9 char s[10];
    10 int read(){
    11     int x=0,f=1; char ch=getchar();
    12     while (ch>'9'||ch<'0'){ if (ch=='-') f=-1; ch=getchar(); }
    13     while (ch<='9'&&ch>='0'){ x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); }
    14     return x*f;
    15 }
    16 void up(int v){
    17     tree[v]=tree[v<<1]+tree[v<<1|1];
    18 }
    19 void down(int v,int mid,int l,int r){
    20     if (mark[v]){
    21         mark[v<<1]+=mark[v];
    22         mark[v<<1|1]+=mark[v];
    23         tree[v<<1]+=(ll)(mid-l+1)*mark[v];
    24         tree[v<<1|1]+=(ll)(r-mid)*mark[v];
    25         mark[v]=0;
    26     }
    27 }
    28 void build(int v,int l,int r){
    29     if (l==r){
    30         tree[v]=sum[l];
    31         return;
    32     }
    33     int mid=(l+r)>>1;
    34     build(v<<1,l,mid);
    35     build(v<<1|1,mid+1,r);
    36     up(v);
    37 }
    38 void change(int v,int l,int r,int x,int y,int k){
    39     if (x<=l&&y>=r){
    40         mark[v]+=k;
    41         tree[v]+=(ll)(r-l+1)*k;
    42         return;
    43     }
    44     int mid=(l+r)>>1;
    45     down(v,mid,l,r);
    46     if (y<=mid) change(v<<1,l,mid,x,y,k); else
    47     if (x>mid) change(v<<1|1,mid+1,r,x,y,k); else{
    48         change(v<<1,l,mid,x,mid,k);
    49         change(v<<1|1,mid+1,r,mid+1,y,k);
    50     }
    51     up(v);
    52 }
    53 ll query(int v,int l,int r,int x,int y){
    54     if (x<=l&&y>=r) return tree[v];
    55     int mid=(l+r)>>1;
    56     down(v,mid,l,r);
    57     if (y<=mid) return query(v<<1,l,mid,x,y); else
    58     if (x>mid) return query(v<<1|1,mid+1,r,x,y); else
    59     return query(v<<1,l,mid,x,mid)+query(v<<1|1,mid+1,r,mid+1,y);
    60 }
    61 int main(){
    62     n=read(); m=read();
    63     for (int i=1;i<=n;i++) a[i]=read();
    64     for (int i=1;i<=n;i++) sum[i]=sum[i-1]+(ll)a[i];
    65     build(1,1,n);
    66     for (int i=1;i<=m;i++){
    67         scanf("%s",s);
    68         if (s[0]=='Q'){
    69             x=read();
    70             printf("%lld
    ",query(1,1,n,1,x));
    71         } else{
    72             p=read(); x=read();
    73             change(1,1,n,p,n,x-a[p]);
    74             a[p]=x;
    75         }
    76     }
    77     return 0;
    78 } 
    View Code
  • 相关阅读:
    day74test
    day73
    drf节流
    drf面试题及总结
    day72test
    日常积累
    windows 内核下获取进程路径
    转:浅析C++中的this指针
    vc 获取窗口标题GetWindowText
    驱动自定义回调例程
  • 原文地址:https://www.cnblogs.com/zhuchenrui/p/7807623.html
Copyright © 2011-2022 走看看