zoukankan      html  css  js  c++  java
  • Big Water Problem (线段树)

    Big Water Problem

    题目描述

    给一个数列,会有多次询问,对于每一次询问,会有两种操作:
    1:给定两个整数x, y, 然后在原数组的第x位置上加y;
    2:给定两个整数l,r,然后输出数组从第l位加到第r位数字的和并换行

    输入描述:

    第一行有两个整数n, m(1 <= n, m <= 100000)代表数列的长度和询问的次数
    第二行n个数字,对于第i个数字a[i],(0<=a[i]<=100000)。
    接下来m行,每一行有三个整数f, x, y。第一个整数f是1或者是2,代表操作类型,如果是1,接下来两个数x,y代表第x的位置上加y,如果是2,则求x到y的和,保证数据合法。

    输出描述:

    输出每次求和的结果并换行
    示例1

    输入

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

    输出

    64



    思路:线段树的单点修改加区间查询......


      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<map>
      7 #include<set>
      8 #include<vector>
      9 using namespace std;
     10 #define ll long long
     11 const int inf=99999999;
     12 const int mod=1e9+7;
     13 const int maxn=100000+10;
     14 typedef struct 
     15 {
     16     int left;
     17     int right;
     18     ll int weight;
     19     ll int lan;
     20 } St;
     21 St tree[maxn<<2];
     22 int n,m;
     23 int a,b;
     24 ll int ans;
     25 ll int num; 
     26 inline void build_tree(int k,int left,int right)//建树 
     27 {
     28     tree[k].left=left;
     29     tree[k].right=right;
     30     if(left==right)
     31     {
     32         cin>>tree[k].weight;
     33         return ;
     34     }
     35     int mid=(left+right)>>1;
     36     build_tree(k<<1,left,mid);//左子树
     37     build_tree(k<<1|1,mid+1,right);//右子树
     38     tree[k].weight=tree[k<<1].weight+tree[k<<1|1].weight;//状态合并,该节点权重等于左子树加右子树权重 
     39 }
     40 inline void lan_down(int k)//树懒标记下传 
     41 {
     42     tree[k<<1].lan+=tree[k].lan;
     43     tree[k<<1|1].lan+=tree[k].lan;
     44     tree[k<<1].weight+=tree[k].lan*(tree[k<<1].right-tree[k<<1].left+1);
     45     tree[k<<1|1].weight+=tree[k].lan*(tree[k<<1|1].right-tree[k<<1|1].left+1);
     46     tree[k].lan=0;
     47 }
     48 inline void ask_point(int k)//单点查询 
     49 {
     50     if(tree[k].left==tree[k].right)
     51     {
     52         ans=tree[k].weight;
     53         return ;
     54     }
     55     if(tree[k].lan)
     56         lan_down(k);
     57     int mid=(tree[k].left+tree[k].right)>>1;
     58     if(a<=mid)//a表示单点询问位置 
     59         ask_point(k<<1);//目标位置靠左,递归左孩子
     60     else
     61         ask_point(k<<1|1);//目标位置靠右,递归右孩子
     62 }
     63 inline void add_point(int k)//单点修改 
     64 {
     65     if(tree[k].left==tree[k].right)
     66     {
     67         tree[k].weight+=num;//单点增加num 
     68         return ;
     69     }
     70     if(tree[k].lan)//树懒标记下传 
     71         lan_down(k);
     72     int mid=(tree[k].left+tree[k].right)>>1;
     73     if(a<=mid)
     74         add_point(k<<1);
     75     else
     76         add_point(k<<1|1);
     77     tree[k].weight=tree[k<<1].weight+tree[k<<1|1].weight;//状态合并 
     78 }
     79 inline void ask_qujian(int k)//区间查询 
     80 {
     81     if(tree[k].left>=a&&tree[k].right<=b)//包含了left,right当前区间,全加上 
     82     {
     83         ans+=tree[k].weight;
     84         return ;
     85     }
     86     if(tree[k].lan)//树懒标记下传 
     87         lan_down(k);
     88     int mid=(tree[k].left+tree[k].right)>>1;
     89     if(a<=mid)//递归查询左子区间 
     90         ask_qujian(k<<1);
     91     if(b>mid)//递归查询右子区间
     92         ask_qujian(k<<1|1);
     93 }
     94 inline void add_qujian(int k)//区间修改 
     95 {
     96     if(tree[k].left>=a&&tree[k].right<=b)
     97     {
     98         tree[k].weight+=num*(tree[k].right-tree[k].left+1);
     99         tree[k].lan+=num;
    100         return ;
    101     }
    102     if(tree[k].lan)
    103         lan_down(k);
    104     int mid=(tree[k].left+tree[k].right)>>1;
    105     if(a<=mid)
    106         add_qujian(k<<1);
    107     if(b>mid)
    108         add_qujian(k<<1|1);
    109     tree[k].weight=tree[k<<1].weight+tree[k<<1|1].weight;//状态合并 
    110 }
    111 int main()
    112 {
    113     ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    114     cin>>n>>m; //n个节点,m个操作 
    115     build_tree(1,1,n);//建树
    116     int op;
    117     for(int i=0;i<m;i++)
    118     {
    119         cin>>op; 
    120         if(op&1)
    121         {
    122             cin>>a>>num;
    123             add_point(1);//单点修改 
    124         }
    125         else
    126         {
    127             cin>>a>>b;
    128             ans=0;
    129             ask_qujian(1);
    130             cout<<ans<<endl;
    131         }
    132     }
    133     return 0;
    134 }



    大佬见笑,,
  • 相关阅读:
    金额转中国大写
    double 四舍五入保留一定的位数
    通过ajax提交表单上传文件
    微信扫码提示浏览器打开的
    在Servlet中获取spring容器WebApplicationContext
    Oracle CONNECT by 简单用法
    JS 删除Array对象中的元素。
    数据导出excel
    DWZ 在js中刷新某个navTab
    Python发送邮件
  • 原文地址:https://www.cnblogs.com/xwl3109377858/p/10917505.html
Copyright © 2011-2022 走看看