zoukankan      html  css  js  c++  java
  • A Simple Problem with Integers POJ

    You have N integers, A1A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

    Input

    The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
    The second line contains N numbers, the initial values of A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
    Each of the next Q lines represents an operation.
    "C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
    "Q a b" means querying the sum of AaAa+1, ... , Ab.

    Output

    You need to answer all Q commands in order. One answer in a line.

    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

    Hint

    The sums may exceed the range of 32-bit integers.
     
    题意:有n个整数,你需要执行两种操作 第一种:Q a b 。表示查询从a到b的所有数的和,第二种:C a b c 。表示把从a到b的所有数都加上c包括a和b。你需要按顺序给出所有查询的语句。
    输入:第一行n ,q,来表示有n个数,q表示有多少个语句1<=n,q<=100000.第二行为n个数的初始数值:A1,A2,A3,,,,An,-100000000<=Ai<=100000000.接下来是q个查询语句。注意结果的总和可能超过32为整数
     
    思路:线段树的模板,用到了区间加和,懒惰标记,和区间求和,比较注意的 是数比较大,所以我用的是longlong,
     
    代码:
      1 #include <cstdio>
      2 #include <fstream>
      3 #include <algorithm>
      4 #include <cmath>
      5 #include <deque>
      6 #include <vector>
      7 #include <queue>
      8 #include <string>
      9 #include <cstring>
     10 #include <map>
     11 #include <stack>
     12 #include <set>
     13 #include <sstream>
     14 #include <iostream>
     15 #define mod 998244353
     16 #define eps 1e-6
     17 #define ll long long
     18 #define INF 0x3f3f3f3f
     19 using namespace std;
     20 
     21 struct node
     22 {
     23     //l表示左边,r表示右边,sum表示该线段的值
     24     ll l,r,sum;
     25     ll lazy;
     26 };
     27 node no[600000];
     28 //存放每个点的值
     29 ll number[100000];
     30 
     31 inline void update(int k)
     32 {
     33     //用左右线段的值更新该线段的值
     34     no[k].sum=no[k*2].sum+no[k*2+1].sum;
     35 }
     36 //初始化
     37 //k表示当前节点的编号,l表示当前区间的左边界,r表示当前区间的右边界
     38 void build(ll k,ll l,ll r)
     39 {
     40     no[k].lazy=0;
     41     no[k].l=l;
     42     no[k].r=r;
     43     //如果递归到最低点
     44     if(l==r)
     45     {
     46         //赋值并记录该点对应的节点编号
     47         no[k].sum=number[l];
     48         return ;
     49     }
     50     //对半分
     51     ll mid=(l+r)/2;
     52     //递归到左线段
     53     build(k*2,l,mid);
     54     //递归到右线段
     55     build(k*2+1,mid+1,r);
     56     update(k);
     57 }
     58 void pushdown(ll k)
     59 {
     60     //如果节点k已经是叶节点了,没有子节点,那么标记就不用下传,直接删除就可以了
     61     if(no[k].l==no[k].r)
     62     {
     63         no[k].lazy=0;
     64         return ;
     65     }
     66     //给k的子节点重新赋值
     67     no[k*2].sum+=(no[k*2].r-no[k].l+1)*no[k].lazy;
     68     no[k*2+1].sum+=(no[k*2+1].r-no[k*2+1].l+1)*no[k].lazy;
     69     //下传点k的标记
     70     no[k*2].lazy+=no[k].lazy;
     71     no[k*2+1].lazy+=no[k].lazy;
     72     //清空点k的标记
     73     no[k].lazy=0;
     74 }
     75 
     76 void change(ll k,ll l,ll r,ll x)
     77 {
     78         //如果当前节点被打上了懒惰标记,那么就把这个标记下传,
     79     if(no[k].lazy)
     80     {
     81         pushdown(k);
     82     }
     83 
     84     if(no[k].l==l&&no[k].r==r)
     85     {
     86         no[k].sum+=(r-l+1)*x;
     87         no[k].lazy+=x;
     88         return ;
     89     }
     90 
     91     ll mid = (no[k].l+no[k].r)/2;
     92     if(r<=mid)
     93     {
     94         change(k*2,l,r,x);
     95     }
     96     else if(l>mid)
     97     {
     98         change(k*2+1,l,r,x);
     99     }
    100     else
    101     {
    102         change(k*2,l,mid,x);
    103         change(k*2+1,mid+1,r,x);
    104     }
    105     update(k);
    106 }
    107 
    108 //查询指定区间内的所有的和
    109 //k表示当前节点的编号,l表示当前区间的左边界,r表示当前区间的右边界
    110 ll query(ll k,ll l,ll r)
    111 {
    112     //如果当前区间就是询问区间,完全重合,那么显然可以直接返回
    113     if(no[k].l==l&&no[k].r==r)
    114     {
    115         return no[k].sum;
    116     }
    117     //如果当前节点被打上了懒惰标记,那么就把这个标记下传,
    118     if(no[k].lazy)
    119     {
    120         pushdown(k);
    121     }
    122     //取中值
    123     ll mid = (no[k].l+no[k].r)/2;
    124     //如果询问区间包含在左子区间中
    125     if(r<=mid)
    126     {
    127         return query(k*2,l,r);
    128     }
    129     else if(l>mid)//如果询问区间包含在右子区间中
    130     {
    131         return query(k*2+1,l,r);
    132     }
    133     else//如果询问区间跨越两个子区间
    134     {
    135         return query(k*2,l,mid)+query(k*2+1,mid+1,r);
    136     }
    137 }
    138 
    139 int main()
    140 {
    141     ll m,n;
    142     scanf("%I64d %I64d",&m,&n);
    143     for(ll i=1;i<=m;i++)
    144     {
    145         scanf("%I64d",&number[i]);
    146     }
    147     build(1,1,m);
    148     char str[2];
    149     ll a,b,c;
    150     while(n--)
    151     {
    152         cin>>str;
    153         if(str[0]=='Q')
    154         {
    155             scanf("%I64d %I64d",&a,&b);
    156             printf("%I64d
    ",query(1,a,b));
    157         }
    158         else if(str[0]=='C')
    159         {
    160             scanf("%I64d %I64d %I64d",&a,&b,&c);
    161             change(1,a,b,c);
    162         }
    163     }  
    164 }
  • 相关阅读:
    vue.js click点击事件获取当前元素对象及获取自定义属性
    在C#的MVC中 Vue的基本用法实例
    使用Dictionary做特殊的json字符串时(可以随意起key的名称)怎么将json字符串反序列化为json匿名对象?及匿名对象的使用方法
    C#生成城市按照一定格式且按字母顺序的方法
    sid-msg.map文件概述
    Linux中 /boot 目录介绍 【转载】
    suricata 命令行解释【转】
    Ubuntu下查看软件版本及安装位置【转】
    linux top命令查看内存及多核CPU的使用讲述【转】
    linux下如何查看多核负载情况【转】
  • 原文地址:https://www.cnblogs.com/mzchuan/p/11768073.html
Copyright © 2011-2022 走看看