zoukankan      html  css  js  c++  java
  • POJ 3498 线段树

    题目:http://poj.org/problem?id=3468

    题意:在一组数中执行两种操作
    "C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
    "Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
     
    [线段树][延时更新]
      注意:区间长度为s[u].r-s[u].l+1,加1容易被忽略;延时更新s[u].add+=ad,因为是延时更新可能之前存的还没有往后加;
      提示:本题只适用线段树;树状数组能解决的问题线段树都能解决;但线段树是O(nlogn),而树状数组是O(logn),且树状数组的代码实现更简单;
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<queue>
      4 #include<algorithm>
      5 #include<cstring>
      6 #define L(u) (u<<1)
      7 #define R(u) (u<<1|1)
      8 using namespace std;
      9 int a[400000];
     10 int n,q;
     11 struct poin{
     12     int l,r;
     13     long long sum;
     14     long long add;
     15 }s[400000];
     16 void upush(int u)
     17 {
     18     s[u].sum=s[L(u)].sum+s[R(u)].sum;
     19     return ;
     20 }
     21 void downpush(int u)
     22 {
     23     s[L(u)].add+=s[u].add;
     24     s[R(u)].add+=s[u].add;
     25     s[L(u)].sum+=(s[L(u)].r-s[L(u)].l+1)*s[u].add;
     26     s[R(u)].sum+=(s[R(u)].r-s[R(u)].l+1)*s[u].add;
     27     s[u].add=0;
     28     return ;
     29 }
     30 void adding(int u,int left,int right,int ad)
     31 {
     32     if(left<=s[u].l&&right>=s[u].r)
     33     {
     34         s[u].sum+=(s[u].r-s[u].l+1)*ad;
     35         s[u].add+=ad;
     36         return ;    
     37     }
     38     if(s[u].add)downpush(u);
     39     int mid=(s[u].l+s[u].r)>>1;
     40     if(right<=mid)
     41         adding(L(u),left,right,ad);
     42       else if(left>mid)
     43         adding(R(u),left,right,ad);
     44     else 
     45     {
     46         adding(L(u),left,mid,ad);
     47         adding(R(u),mid+1,right,ad);
     48     }
     49     upush(u);
     50 }
     51 long long query(int u,int left,int right)
     52 {
     53     if(left<=s[u].l&&right>=s[u].r)
     54         return s[u].sum;
     55     if(s[u].add)downpush(u);
     56     int mid=(s[u].l+s[u].r)>>1;
     57     if(right<=mid)return query(L(u),left,right);
     58     else if(left>mid)return query(R(u),left,right);
     59     else return (query(L(u),left,mid)+query(R(u),mid+1,right));
     60     upush(u);
     61 }
     62 void build(int u,int left,int right)
     63 {
     64     s[u].l=left;
     65     s[u].r=right;
     66     if(s[u].l==s[u].r)
     67     {
     68         s[u].sum=a[left];
     69         return ;
     70     }
     71     int mid=(left+right)>>1;
     72     build(L(u),left,mid);
     73     build(R(u),mid+1,right);
     74     upush(u);
     75     
     76 }
     77 int main()
     78 {
     79     cin>>n>>q;
     80     for(int i=1;i<=n;i++)
     81     scanf("%d",&a[i]);
     82     build(1,1,n);
     83     for(int i=1;i<=q;i++)
     84     {
     85         char w;
     86         w=getchar();
     87         while(w!='C'&&w!='Q')
     88         w=getchar();
     89         if(w=='C')
     90         {
     91             int y,o,u;
     92             scanf("%d%d%d",&y,&o,&u);
     93             adding(1,y,o,u);
     94         }
     95         if(w=='Q')
     96         {
     97             int y,o;
     98             scanf("%d%d",&y,&o);
     99             long long e=query(1,y,o);
    100             cout<<e;
    101             printf("
    "); 
    102         }
    103     }
    104     return 0;
    105 }
  • 相关阅读:
    C#获取局域网MAC地址
    查看Linux是32位还是64位的方法
    JS判断不能为空实例代码
    SQL2005数据库行列转换
    mysql 导入导出数据库、数据表的方法
    linux kill 关闭进程命令
    设置CentOS控制台分辨率图文详解
    Windows 2003 IIS 不支持ASP问题的解决方法
    稳聘App设计图分享
    Sql 中存储过程详细案例
  • 原文地址:https://www.cnblogs.com/nigulasi/p/5665667.html
Copyright © 2011-2022 走看看