• POJ 3468


    C - A Simple Problem with Integers
    Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u
    Appoint description: 

    Description

    给出了一个序列,你需要处理如下两种询问。

    "C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。

    "Q a b" 询问[a, b]区间中所有值的和。

    Input

    第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000.

    第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。

    接下来Q行询问,格式如题目描述。

    Output

    对于每一个Q开头的询问,你需要输出相应的答案,每个答案一行。

    Sample Input

    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 4 4
    Q 1 10
    Q 2 4
    C 3 6 3
    Q 2 4

     

    Sample Output

    4
    55
    9
    15

    题意:中文题

    思路:这种 n*n 的查询更新,肯定用线段树。但是不能单点更新,如果单点更新的话,相当于将区间内所有点都递归到树的最后一层再更新。因此要利用区间更新,大致思路是:1,对每个结点,除了设置 sum 变量之外,再存一个 add 变量用来整个区间被更新的次数。递归过程中如果碰到 ll == l && rr == r 的情况,不必向下更新,直接更新这个区间的 add。 2,每次递归 update 时要更新当前 sum。(更新的必要性也有写到) 3,查询时又上到下传递 add 参数,最后要 return sum+(区间长度)*addd; 

    具体有些细节注释中写到了。

    代码:

     1 #include <iostream>
     2 #include <string>
     3 using namespace std;
     4 
     5 struct Node{
     6     int l,r;
     7     long long add;
     8     long long sum;
     9 }node[100000*4+5];
    10 int a[100005];
    11 
    12 void build(int id,int l,int r){
    13     node[id].l = l;
    14     node[id].r = r;
    15     node[id].add = 0;
    16 
    17     if(l == r){
    18         node[id].sum = a[l];
    19         return ;
    20     }
    21     int mid = (l+r)>>1;
    22     build(id*2,l,mid);
    23     build(id*2+1,mid+1,r);
    24 
    25     node[id].sum = node[id*2].sum+node[id*2+1].sum;
    26 }
    27 long long query(int id,int l,int r,long long c){        //c为到该层为止,包含该层子区间的结点共更新了多少次。每次递归需累加
    28     int ll = node[id].l;
    29     int rr = node[id].r;
    30     int mid = (ll+rr)>>1;
    31     int addd = node[id].add;
    32 
    33     //if(ll == rr)  return node[id].sum + c+addd;
    34     if(ll == l && rr == r)
    35         return node[id].sum +  (r-l+1)*(c);
    36     if(r <= mid)
    37         return query(id*2,l,r,c+addd);
    38     else if(l > mid)
    39         return query(id*2+1,l,r,c+addd);
    40     else
    41         return query(id*2,l,mid,c+addd) + query(id*2+1,mid+1,r,c+addd);
    42 }
    43 void update(int id,int l,int r,int c){
    44     int ll = node[id].l;
    45     int rr = node[id].r;
    46     int mid = (ll+rr)>>1;
    47 
    48     node[id].sum += (r-l+1)*c;      //下层区间更新了,但是该层的add未更新,所以要修改该层的sum
    49     if(ll == l && rr == r){     //用更新区间代替点
    50         node[id].add += c;
    51         return ;
    52     }
    53     if(r <= mid)
    54         update(id*2,l,r,c);
    55     else if(l > mid)
    56         update(id*2+1,l,r,c);
    57     else{
    58         update(id*2,l,mid,c);
    59         update(id*2+1,mid+1,r,c);
    60     }
    61 }
    62 
    63 int main()
    64 {
    65     ios_base::sync_with_stdio(0);
    66     cin.tie(0);
    67     int n,m;
    68     while(cin>>n>>m){
    69         for(int i = 1;i <= n;i ++)  cin>>a[i];
    70 
    71         build(1,1,n);
    72         string s;
    73         int ai,bi,ci;
    74         for(int i = 1;i <= m;i ++){
    75             cin>>s;
    76             if(s[0] == 'Q'){
    77                 cin>>ai>>bi;
    78                 long long ans = query(1,ai,bi,0);
    79                 cout<<ans<<endl;
    80             }
    81             if(s[0] == 'C'){
    82                 cin>>ai>>bi>>ci;
    83                 update(1,ai,bi,ci);
    84             }
    85         }
    86     }
    87     return 0;
    88 }
    View Code


  • 相关阅读:
    zookeeper
    redis客户端高低版本简单实战、雪崩、击穿、穿透、布隆过滤器(三)
    redis集群理论与实战(二)
    redis集群理论与实战
    oracle单表循环修改表字段
    redis的集群、主从复制、CAP、paxos
    CF1328D Carousel
    AT4842 [ABC136E] Max GCD
    [ABC135D] Digits Parade
    AT4752 [ABC131E] Friendships
  • 原文地址:https://www.cnblogs.com/Jstyle-continue/p/6351937.html
Copyright © 2020-2023  润新知