zoukankan      html  css  js  c++  java
  • kuangbin专题七 POJ3468 A Simple Problem with Integers (线段树或树状数组)

    You have N integers, A1, A2, ... , 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 A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
    Each of the next Q lines represents an operation.
    "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.

    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


    区间修改 区间查询 注意pushdown的操作就可以了

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <math.h>
      4 #include <string.h>
      5 #include <stdlib.h>
      6 #include <string>
      7 #include <vector>
      8 #include <set>
      9 #include <map>
     10 #include <queue>
     11 #include <algorithm>
     12 #include <sstream>
     13 #include <stack>
     14 using namespace std;
     15 #define FO freopen("in.txt","r",stdin);
     16 #define rep(i,a,n) for (int i=a;i<n;i++)
     17 #define per(i,a,n) for (int i=n-1;i>=a;i--)
     18 #define pb push_back
     19 #define mp make_pair
     20 #define all(x) (x).begin(),(x).end()
     21 #define fi first
     22 #define se second
     23 #define SZ(x) ((int)(x).size())
     24 #define debug(x) cout << "&&" << x << "&&" << endl;
     25 #define lowbit(x) (x&-x)
     26 #define mem(a,b) memset(a, b, sizeof(a));
     27 typedef vector<int> VI;
     28 typedef long long ll;
     29 typedef pair<int,int> PII;
     30 const ll mod=1000000007;
     31 const int inf = 0x3f3f3f3f;
     32 ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
     33 ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
     34 //head
     35 
     36 //区间修改 区间查询
     37 const int maxx=100010;
     38 ll sum[maxx<<2],lazy[maxx<<2],val;
     39 int n,q;
     40 
     41 void Pushup(int rt) {
     42     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
     43 }
     44 
     45 void build(int rt,int L,int R) {
     46     lazy[rt]=0;
     47     if(L==R) {
     48         scanf("%lld",&sum[rt]);
     49         return;
     50     }
     51     int mid=(L+R)>>1;
     52     build(rt<<1,L,mid);
     53     build(rt<<1|1,mid+1,R);
     54     Pushup(rt);
     55 }
     56 
     57 void Pushdown(int rt,int x) {
     58     if(lazy[rt]) {
     59         lazy[rt<<1]+=lazy[rt];
     60         lazy[rt<<1|1]+=lazy[rt];
     61         sum[rt<<1]+=(x-(x>>1))*lazy[rt];//左子树加左边一半的值
     62         sum[rt<<1|1]+=(x>>1)*lazy[rt];//右子树同理
     63         lazy[rt]=0;//清空
     64     }    
     65 }
     66 
     67 void Updata(int rt,int L,int R,int l,int r) {
     68     if(L>=l&&R<=r) {
     69         lazy[rt]+=val;//累加标记
     70         sum[rt]+=(R-L+1)*val;//更新值
     71         return;
     72     }
     73     int mid=(L+R)>>1;
     74     Pushdown(rt,R-L+1);//这里多了一个参数 L R区间的个数
     75     if(l<=mid) Updata(rt<<1,L,mid,l,r);
     76     if(r>mid) Updata(rt<<1|1,mid+1,R,l,r);
     77     Pushup(rt);
     78 }
     79 
     80 ll Query(int rt,int L,int R,int l,int r) {
     81     if(L>=l&&R<=r)
     82         return sum[rt];
     83     ll ans=0;
     84     int mid=(L+R)>>1;
     85     Pushdown(rt,R-L+1);
     86     if(l<=mid) ans+=Query(rt<<1,L,mid,l,r);
     87     if(r>mid) ans+=Query(rt<<1|1,mid+1,R,l,r);
     88     Pushup(rt);
     89     return ans;
     90 }
     91 
     92 
     93 int main() {
     94     while(~scanf("%d%d",&n,&q)) {
     95         build(1,1,n);
     96         char s[3];
     97         while(q--) {
     98             scanf("%s",s);
     99             int l,r;
    100             if(s[0]=='Q') {
    101                 scanf("%d%d",&l,&r);
    102                 printf("%lld
    ",Query(1,1,n,l,r));
    103             } else {
    104                 scanf("%d%d%lld",&l,&r,&val);
    105                 Updata(1,1,n,l,r);
    106             }
    107         }
    108     }
    109 }
    View Code

    借此机会学习了一波树状数组,有点难理解。

    单点修改 区间查询  Updata(l,val)

    区间修改 单点查询  引入差分数组 c[i]=d[i]-d[i-1]; Updata(l,val);  Updata(r+1,-val); ----明白树状数组就好理解了。把多加的减去

    区间修改 区间查询  公式可以推到一下,sum[n]=n*(c[1]+c[2]+...c[n])-(0*c[1]+1*c[2]+2*c[3]+...+(n-1)*c[n]);

    所以再维护一个 (i-1)*(a[i]-a[i-1]) , a为原数组。

    Updata(l,(l-1)*val); Updata(r+1,-r*val);   原理同上。多加的减去。

    (纯属个人理解。关键还是公式的推导,和树状数组的理解)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 typedef long long ll;
     6 #define lowbit(x) (x&-x)
     7  
     8 int n,q;
     9 const int maxn=100010;
    10 ll a[maxn],val,c1[maxn],c2[maxn];//维护两个树状数组
    11 
    12 void Updata(ll c[],int pos,ll val) {
    13     while(pos<=n) {
    14         c[pos]+=val;
    15         pos+=lowbit(pos);
    16     }
    17 } 
    18 
    19 ll getsum(ll c[],int pos) {
    20     ll ans=0;
    21     while(pos>0) {
    22         ans+=c[pos];
    23         pos-=lowbit(pos);
    24     }
    25     return ans;
    26 }
    27 
    28 ll sigma(int r) {//公式推导
    29     ll sum1=r*getsum(c1,r);
    30     ll sum2=getsum(c2,r);
    31     return sum1-sum2;
    32 }
    33 
    34 ll Query(int l,int r) {//区间求和
    35     return sigma(r)-sigma(l-1);
    36 }
    37 
    38 int main() {
    39     while(~scanf("%d%d",&n,&q)) {
    40         memset(c1,0,sizeof(c1));memset(c2,0,sizeof(c2));
    41         for(int i=1;i<=n;i++) { 
    42             scanf("%lld",&a[i]);
    43             Updata(c1,i,a[i]-a[i-1]);//维护a[i]-a[i-1]
    44             Updata(c2,i,(i-1)*(a[i]-a[i-1]));//维护(i-1)*(a[i]-a[i-1])
    45         } 
    46         char s[2];
    47         while(q--) {
    48             int l,r;
    49             scanf("%s",s);
    50             if(s[0]=='Q') {
    51                 scanf("%d%d",&l,&r);
    52                 printf("%lld
    ",Query(l,r));
    53             } else {
    54                 scanf("%d%d%lld",&l,&r,&val);
    55                 //更新操作有点难理解
    56                 Updata(c1,l,val);Updata(c1,r+1,-val);
    57                 Updata(c2,l,(l-1)*val);Updata(c2,r+1,-r*val);
    58             }
    59         }
    60     }
    61 }
    View Code
  • 相关阅读:
    找出优先要作的工作
    我要作技术研发了
    确定配色方案
    今天公司搬家
    要作界面原型了
    使用自已的命名空间
    进行审核了
    那里有皮肤软件工开发包的源码???
    发葡萄
    作业务规则挺难
  • 原文地址:https://www.cnblogs.com/ACMerszl/p/9839767.html
Copyright © 2011-2022 走看看