NOIP专题(二) 线段树与树状数组

一.动态连续和查询问题
问题描述

给定一个n个元素的数组a1,a2,a3…..an,你的任务是设计一个数据结构支持以下两种操作:

(1)Add(x,d): 让a[x]增加d

(2)Query(L,R): 计算L到R的区间和

输入文件

输入的第 1 行包含一个整数 n 表示序列长度。

接下来一行包含n个整数,分别是A[1], A[2], …, A[n]。

接下来一行包含一个整数m,表示询问个数。

接下来每行一个询问:

0 x y : 将 A[x]增加y

1 x y : 询问x到y的区间和

输出文件

对于每个询问1 x y,输出一行为要求的答案。

输出样例
4
1 2 3 4
4
1 1 3
0 3 -3
1 2 4
1 3 3
输出样例
6
6
0

#include 
#include 
#include 
using namespace std;
int n,m;
int q,l,r;
int f[1000005];
int f1[1000006];
int k;
inline int lowbit(int x)
{
    return x&(-x);
}
inline int get(int x)
{
    int sum=0;
    for(int i=x;i>0;i-=lowbit(i))
    {
        sum+=f[i];
    }
    return sum;
}
void add1(int x,int d)
{
    for(int i=x;i<=n;i=i+lowbit(i)){f[i]=f[i]+d;}
    return;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&q);
        add1(i,q);
    }
    scanf("%d",&m);
    for (int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d%d",&k,&x,&y);
        if (k==0) add1(x,y);
        if (k==1) printf("%d\n",get(y)-get(x-1));
    }
    return 0;
}

二.数列操作1
问题描述

给定一个初始值都为0的序列,动态地修改一些位置上的数字,加上一个数,减去一个数,或者乘上一个数,然后动态地提出问题,问题的形式是求出一段数字的和。

输入文件

输入数据第一行包含2个整数N,M(1≤N,M≤100000),表示序列的长度和操作的次数。

接下来M行,每行会出现如下的一种格式:

1 i x ——将序列中第i个数加上x

2 i x ——将序列中第i个数减去x

3 i x ——将序列中第i个数乘上x

4 i j ——求出序列中第i个数到第j个数的和

输出文件

对于每一个Query操作输出一个数,表示序列中第i个数到第j个数的和。

样例输入
10
5
1 3 2
2 4 1
3 3 2
4 1 3
4 2 4
样例输出
4
3

#include 
#include 
#include 
#include 
using namespace std;
int n,m;
int c[100005];
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline int lowbit(int x){return x&(-x);}
inline void add(int x,int y){
    for(int i=x;i<=n;i+=lowbit(i)) c[i]+=y;
}
inline int gett(int x){
     int anss=0;
     for(int i=x;i;i-=lowbit(i)) anss+=c[i];
     return anss;
}
int main(){
     n=read();m=read();
     for(int i=1;i<=m;i++){
        int ord,x,y;
        ord=read();x=read();y=read();
        if(ord==1){
            add(x,y);
        }
        if(ord==2){
            add(x,-1*y);
        }
        if(ord==3){
            int bb=gett(x)-gett(x-1);
            add(x,(y-1)*bb);
        }
        if(ord==4){
            printf("%d\n",gett(y)-gett(x-1));
        }
     }
   return 0;
}

三.数列操作二
问题描述

给定一个初始值都为0的序列,动态地修改一个区间,加上一个数,减去一个数,,然后动态地提出问题,问题的形式是求出某一点的值。

输入文件

输入数据第一行包含2个整数N,M(1≤N,M≤1000000),表示序列的长度和操作的次数。

接下来M行,每行会出现如下的一种格式:

1 i j x——将第i个数到第j个数加上x

2 i j x ——将第i个数到第j个数减去x

3 i ——查询i点的值。

输出文件

对于每一个Query操作输出一个数。

样例输入
10
5
1 2 3 4
2 1 4 5
1 3 7 5
3 3
3 7
样例输出
4
5

#include 
#include 
#include 
#include 
using namespace std;
int n,m;
int a[100005];
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct NODE{
    int l,r;
    long long sum,maxx,lazy,minn,b;
    NODE *ls,*rs;
    NODE():ls(NULL),rs(NULL),lazy(0){}
    inline void maintain(){
      sum=ls->sum+rs->sum;
      maxx=max(ls->maxx,rs->maxx);
      minn=min(ls->minn,rs->minn);
    }
    inline void pushdown(int l,int r){
        int mid=(l+r)>>1;
        if(lazy){
            ls->maxx+=lazy;
            ls->minn+=lazy;
            rs->minn+=lazy;
            ls->maxx+=lazy;
            ls->lazy+=lazy;
            rs->lazy+=lazy;
            ls->sum+=(mid-l+1)*lazy;
            rs->sum+=(r-(mid+1)+1)*lazy;
            lazy=0;
        }
    }
}*root;
inline void maketree(int L,int R,NODE *&k){
    k=new NODE;
    if(L==R){
        k->minn=k->maxx=k->sum=a[L];
        return ;
    }
    int mid=(L+R)>>1;
    maketree(L,mid,k->ls);maketree(mid+1,R,k->rs);
    k->maintain();
}
inline void Add(int L,int R,int x,int y,int v,NODE *k){
    if(L>=x && R<=y){
        k->lazy+=v;
        k->minn+=v;
        k->maxx+=v;
        k->sum+=(R-L+1)*v;
        return ;
    }
    k->pushdown(L,R);
    int mid=(L+R)>>1;
    if(y<=mid) Add(L,mid,x,y,v,k->ls);
    else if(x>mid) Add(mid+1,R,x,y,v,k->rs);
    else Add(L,mid,x,y,v,k->ls),Add(mid+1,R,x,y,v,k->rs);
   k->maintain();
}
inline int Query(int L,int R,int x,int y,NODE *k){
    if(L>=x&&R<=y) return k->sum;
    int mid=(L+R)>>1,t;
    k->pushdown(L,R);
    if(y<=mid) t=Query(L,mid,x,y,k->ls);
    else if(x>mid) t=Query(mid+1,R,x,y,k->rs);
    else t=Query(L,mid,x,y,k->ls)+Query(mid+1,R,x,y,k->rs);
    k->maintain();
    return t;
}
int main(){
    n=read();m=read();
    maketree(1,n,root);
    for(int i=1;i<=m;i++){
      int ord,x,y,z;
      ord=read();
      x=read();
      if(ord==1){
        y=read();
        z=read();
        Add(1,n,x,y,z,root);
      }
      else if(ord==2){
          y=read();
          z=read();
          Add(1,n,x,y,-1*z,root);
      }
      else{
         printf("%d\n",Query(1,n,x,x,root));
      }
    }
    return 0;
}

四.求和
问题描述

给定一个序列a1,a2,…..an,动态地修改一个区间,加上一个数,,然后动态询问一个区间的所有元素的和。

输入文件

输入数据第一行包含2个整数N,M(1≤N,M≤1000000),表示序列的长度和操作的次数。

接下一行n个数,表示a1,a2,…..an。

再接下来M行,每行会出现如下的一种格式:

1 i j x——将第i个数到第j个数加上x

2 i j ——输出第i个数到第j个数的和

输出文件

对于每一个Query操作输出一个数,表示序列中第i个数到第j个数的和。

样例输入
10
1 2 3 4 5 6 1 2 3 4
5
1 2 3 4
2 1 4
1 3 7 5
1 2 6 5
2 1 10
样例输出
18
89

#include 
#include 
#include 
using namespace std;
int n,m;
int a[100005];
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct NODE{
    int sum,v;
    NODE *ls,*rs;
    NODE():ls(NULL),rs(NULL),v(0){}
    inline void maintain(){
        sum=ls->sum+rs->sum;
    }
    inline void pushdown(int L,int R){
        int mid=(L+R)>>1;
        if(v){
            ls->v+=v;
            rs->v+=v;
            ls->sum+=(mid-L+1)*v;
            rs->sum+=(R-(mid+1)+1)*v;
            v=0;
        }
    }

}*root;
inline void maketree(int L,int R,NODE *&k){
    k=new NODE ;
    if(L==R){
        k->sum=a[L];
        return ;
    }
    int mid=(L+R)>>1;
    maketree(L,mid,k->ls);
    maketree(mid+1,R,k->rs);
    k->maintain();
}
inline void add(int L,int R,int x,int y,int z,NODE *k){
    if(L>=x&&R<=y){
        k->v+=z;
        k->sum+=(R-L+1)*z;
        return ;
    }
    k->pushdown(L,R);
    int mid=(L+R)>>1;
    if(y<=mid) add(L,mid,x,y,z,k->ls);
    else if(x>mid) add(mid+1,R,x,y,z,k->rs);
    else add(L,mid,x,y,z,k->ls),add(mid+1,R,x,y,z,k->rs);
    k->maintain();
}
inline int Query(int L,int R,int x,int y,NODE *k){
    if(L>=x&&R<=y){
        return k->sum;
    }

    k->pushdown(L,R);
    k->maintain();
    int mid=(L+R)>>1,t;
    if(y<=mid) t=Query(L,mid,x,y,k->ls);
    else if(x>mid) t=Query(mid+1,R,x,y,k->rs);
    else t=Query(L,mid,x,y,k->ls)+Query(mid+1,R,x,y,k->rs);
    return t;
}
int main(){
      n=read();
      for(int i=1;i<=n;i++) a[i]=read();
      maketree(1,n,root);
      m=read();
      for(int i=1;i<=m;i++){
        int ord,x,y,k;
        ord=read();x=read();y=read();
        if(ord==1){
            k=read();
            add(1,n,x,y,k,root);
        }
        else {
            printf("%d\n",Query(1,n,x,y,root));
        }
      }
    return 0;
}

五.
问题描述

给定数列a1, a2, .., an和若干询问(l, r),回答区间最大值。

输入文件

一个整数N表示数字的个数,接下来一行为N个数。第三行读入一个M,表示提问的次数,接下来M行,每行都有两个整数l,r(l<=r)。

输出文件

输出共M行,每行输出一个数,表示提问区间的最大值。

样例输入
6
34 1 8 123 3 2
4
1 2
1 5
3 4
2 3
样例输出
34
123
123
8

#include 
#include 
#include 
using namespace std;
const int INF=2147483640;
int n,m;
int a[200005];
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct NODE{
    int maxn;
    NODE *ls,*rs;
    NODE():ls(NULL),rs(NULL),maxn(-INF){}
    inline void maintain(){
        maxn=max(ls->maxn,rs->maxn);
    }
}*root;
inline void maketree(int l,int r,NODE *&k){
     k=new NODE;
     if(l==r){
         k->maxn=a[l];
         return ;
     }
     int mid=(l+r)>>1;
     maketree(l,mid,k->ls);
     maketree(mid+1,r,k->rs);
     k->maintain();
}
inline int Query(int l,int r,int x,int y,NODE *k){
    if(l>=x&&r<=y){
         return k->maxn;
    }
    int mid=(l+r)>>1,t;
    k->maintain();
    if(y<=mid) t=Query(l,mid,x,y,k->ls);
    else if(x>mid) t=Query(mid+1,r,x,y,k->rs);
    else t=max(Query(l,mid,x,y,k->ls),Query(mid+1,r,x,y,k->rs));
    return t;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    maketree(1,n,root);
    m=read();
    for(int i=1;i<=m;i++){
         int l,r;
         l=read();r=read();
         printf("%d\n",Query(1,n,l,r,root));
    }
    return 0;
}

六.
问题描述

给定数列a1, a2, .., an和若干询问(l, r),回答区间最大连续和。 输入文件 一个整数N表示数字的个数,接下来一行为N个数。第三行读入一个M,表示提问的次数,接下来M行,每行都有两个整数l,r(l<=r)。

输出文件

输出共M行,每行输出一个数,表示提问区间的最大连续和。

样例输入
9
1 3 -3 8 1 9 -5 -2 4
2
1 5
6 9
样例输出
10
9

#include 
#include 
#include 
using namespace std;
const int INF=2147483640;
int n,m;
int a[200005];
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct NODE{
    int sum,lsum,rsum,maxsum;
    NODE *ls,*rs;
    NODE():ls(NULL),rs(NULL),sum(0){}
    inline void maintain(){
        sum=ls->sum+rs->sum;
        lsum=max(ls->lsum,ls->sum+rs->lsum);
        rsum=max(rs->rsum,rs->sum+ls->rsum);
        maxsum=max(ls->rsum+rs->lsum,max(rs->maxsum,ls->maxsum));
    }
}*root;
inline void maketree(int l,int r,NODE *&k){
     k=new NODE;
     if(l==r){
         k->maxsum=k->rsum=k->lsum=k->sum=a[l];
         return ;
     }
     int mid=(l+r)>>1;
     maketree(l,mid,k->ls);
     maketree(mid+1,r,k->rs);
     k->maintain();
}
inline NODE* Query(int l,int r,int x,int y,NODE *k){
      if(l>=x&&r<=y){
          return k;
      }
      int mid=(l+r)>>1;
      NODE *t;
      if(y<=mid) t=Query(l,mid,x,y,k->ls);
      else if(x>mid) t=Query(mid+1,r,x,y,k->rs);
      else{
          NODE *t1=Query(l,mid,x,y,k->ls),*t2=Query(mid+1,r,x,y,k->rs);
          t=new NODE;
          t->sum=t1->sum+t2->sum;
          t->lsum=max(t1->lsum,t1->sum+t2->lsum);
          t->rsum=max(t2->rsum,t2->sum+t1->rsum);
          t->maxsum=max(t1->rsum+t2->lsum,max(t2->maxsum,t1->maxsum));
      }
      return t;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    maketree(1,n,root);
    m=read();
    for(int i=1;i<=m;i++){
        int l,r;
        l=read();r=read();
       printf("%d\n",Query(1,n,l,r,root)->maxsum) ;
    }
    return 0;
}

七.
问题描述

现在你有一个长度为n的序列A,你需要做如下的操作:修改A[i]的值,或者给出x和y询问max{Ai + .. + Aj | x <= i <= j <= y},也就是在x和y之间的最大连续和。

输入文件

输入的第 1 行包含一个整数 n 表示序列长度。

接下来一行包含n个整数,分别是A[1], A[2], …, A[n]。

接下来一行包含一个整数m,表示询问个数。

接下来每行一个询问:

0 x y : 将 A[x]修改为y

1 x y : 询问x到y的最大连续和

输出文件

对于每个询问1 x y,输出一行为要求的答案。

输出样例
4
1 2 3 4
4
1 1 3
0 3 -3
1 2 4
1 3 3
输出样例
6
4
-3

#include 
#include 
#include 
using namespace std;
const int INF=2147483640;
int n,m;
int a[200005];
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct NODE{
     int maxsum,sum,lsum,rsum,b;
     NODE *ls,*rs;
     NODE():ls(NULL),rs(NULL),b(INF){}
     inline void maintain(){
         sum=ls->sum+rs->sum;
         lsum=max(ls->lsum,ls->sum+rs->lsum);
         rsum=max(rs->rsum,rs->sum+ls->rsum);
         maxsum=max(ls->rsum+rs->lsum,max(ls->maxsum,rs->maxsum));
     }
     inline void pushdown(int l,int r){
          int mid=(l+r)>>1;
          if(b!=INF){
              ls->maxsum=ls->lsum=ls->rsum=ls->sum=(mid-l+1)*b;
              rs->maxsum=ls->lsum=ls->rsum=rs->sum=(r-(mid+1)+1)*b;
              b=INF;
          }
     }
}*root;
inline void maketree(int l,int r,NODE *&k){
     k=new NODE;
     if(l==r){
         k->maxsum=k->rsum=k->lsum=k->sum=a[l];
         return ;
     }
     int mid=(l+r)>>1;
     maketree(l,mid,k->ls);
     maketree(mid+1,r,k->rs);
     k->maintain();
}
inline void Modify(int l,int r,int x,int y,int z,NODE *k){
    if(l>=x&&r<=y){
       k->maxsum=k->sum=k->rsum=k->lsum=(r-l+1)*z;
       return ;
    }
    int mid=(l+r)>>1;
     if(y<=mid) Modify(l,mid,x,y,z,k->ls);
     else if(x>mid) Modify(mid+1,r,x,y,z,k->rs);
     else Modify(l,mid,x,y,z,k->ls),Modify(mid+1,r,x,y,z,k->rs);
     k->maintain();
}
inline NODE* Query(int l,int r,int x,int y,NODE *k){
     if(l>=x&&r<=y){
         return k;
     }
     int mid=(l+r)>>1;
     NODE *t;
     if(y<=mid) t=Query(l,mid,x,y,k->ls);
     else if(x>mid) t=Query(mid+1,r,x,y,k->rs);
     else{
        NODE *t1,*t2;
        t=new NODE;
        t1=Query(l,mid,x,y,k->ls);
        t2=Query(mid+1,r,x,y,k->rs);
         t->sum=t1->sum+t2->sum;
         t->lsum=max(t1->lsum,t1->sum+t2->lsum);
         t->rsum=max(t2->rsum,t2->sum+t1->rsum);
         t->maxsum=max(t1->rsum+t2->lsum,max(t1->maxsum,t2->maxsum));
     }
     return t;
}
int main(){
    n=read();for(int i=1;i<=n;i++) a[i]=read();
    maketree(1,n,root);
    m=read();
    for(int i=1;i<=m;i++){
        int ord,x,y;
        ord=read();x=read();y=read();
        if(ord==0){
           Modify(1,n,x,x,y,root);

           // maketree(1,n,root);
        }
        else if(ord==1){
           printf("%d\n",Query(1,n,x,y,root)->maxsum);
        }
    }
    return 0;
}

八.
问题描述

给出一个n(n<=50000)元素组成的序列a1,a2…..an,你是任务是设计一种数据结构,支持以下两种操作:

(1)modify(x,y,v) 把ax到ay的值全部修改为v

(2)query(x,y) 计算子序列ax到ay的元素和、最小值、最大值

输入文件

输入的第 1 行包含一个整数 n 表示序列长度

接下来一行包含n个整数,分别是A[1], A[2], …, A[n]

接下来一行包含一个整数m,表示询问个数

接下来每行一个询问:

0 x y v : 将ax到ay的值全部修改为v

1 x y : 询问x到y的区间和、最小值、最大值

输出文件

对于每个询问1 x y,输出区间和、区间最小值、区间最大值。

样例输入
10
1 -2 3 9 4 -2 1 9 3 5
3
1 2 6
0 2 5 3
1 2 8
样例输出
12 -2 9
20 -2 9

#include 
#include 
#include 
#include 
using namespace std;
const int INF=2147483647;
int n,m;
int a[100005];
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct NODE{
    int lsum,rsum,maxx,minn,v,sum,b;
    NODE *ls,*rs;
    NODE():ls(NULL),rs(NULL),v(0),b(INF){}
    inline void maintain(){
        sum=ls->sum+rs->sum;
        maxx=max(ls->maxx,rs->maxx);
        minn=min(ls->minn,rs->minn);
    }
    inline void pushdown(int l,int r){
        int mid=(l+r)>>1;
        if(b!=INF){
            ls->maxx=ls->minn=rs->maxx=rs->minn=ls->b=rs->b=b;
            ls->v=rs->v=0;
            ls->sum=(mid-l+1)*b;rs->sum=(r-(mid+1)+1)*b;
            b=INF;
        }
        if(v){
           ls->maxx+=v;
           rs->maxx+=v;
           ls->minn+=v;
           rs->minn+=v;
           ls->sum+=(mid-l+1)*v;
           rs->sum+=(r-(mid+1)+1)*v;
           ls->v+=v;
           rs->v+=v;
           v=0;
        }

    }
}*root;
inline void maketree(int l,int r,NODE *&k){
    k=new NODE;
    if(l==r){
       k->minn=k->maxx=k->sum=a[l];
       return ;
    }
    int mid=(l+r)>>1;
    maketree(l,mid,k->ls); maketree(mid+1,r,k->rs);
    k->maintain();
}
inline void add(int L,int R,int x,int y,int z,NODE *k){
     if(L>=x && R<=y){
        k->v+=z;
        k->maxx+=z;
        k->minn+=z;
        k->sum+=(R-L+1)*z;
        return ;
     }
     k->pushdown(L,R);
     int mid=(L+R)>>1;
     if(y<=mid) add(L,mid,x,y,z,k->ls);
     else if(x>mid) add(mid+1,R,x,y,z,k->rs);
     else add(L,mid,x,y,z,k->ls),add(mid+1,R,x,y,z,k->rs);
     k->maintain();
     return ;
}
inline int Query(int L,int R,int x,int y,NODE *k){
     if(L>=x&&R<=y) return k->sum;
     int mid=(L+R)>>1,t;
     k->pushdown(L,R);
     if(y<=mid) t=Query(L,mid,x,y,k->ls);
     else if(x>mid) t=Query(mid+1,R,x,y,k->rs);
     else t=Query(L,mid,x,y,k->ls)+Query(mid+1,R,x,y,k->rs);

     return t;
}
inline int Query2(int L,int R,int x,int y,NODE *k){
     if(L>=x&&R<=y) return k->minn;
     int mid=(L+R)>>1,t;
     k->pushdown(L,R);
     if(y<=mid) t=Query2(L,mid,x,y,k->ls);
     else if(x>mid) t=Query2(mid+1,R,x,y,k->rs);
     else t=min(Query2(L,mid,x,y,k->ls),Query2(mid+1,R,x,y,k->rs));
     return t;
}
inline int Query3(int L,int R,int x,int y,NODE *k){
     if(L>=x&&R<=y) return k->maxx;
     int mid=(L+R)>>1,t;
     k->pushdown(L,R);
     if(y<=mid) t=Query3(L,mid,x,y,k->ls);
     else if(x>mid) t=Query3(mid+1,R,x,y,k->rs);
     else t=max(Query3(L,mid,x,y,k->ls),Query3(mid+1,R,x,y,k->rs));
     return t;
}
inline void Modify(int L,int R,int x,int y,int z,NODE *k){
     if(L>=x&&R<=y){
         k->v=0;
         k->maxx=k->minn=k->b=z;
         k->sum=(R-L+1)*z;
         return ;
     }
     k->pushdown(L,R);
     int mid=(L+R)>>1;
     if(y<=mid) Modify(L,mid,x,y,z,k->ls);
     else if(x>mid) Modify(mid+1,R,x,y,z,k->rs);
     else Modify(L,mid,x,y,z,k->ls),Modify(mid+1,R,x,y,z,k->rs);
    k->maintain();
}
int main(){
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    maketree(1,n,root);
    m=read();
    for(int i=1;i<=m;i++){
      int ord,x,y,v;
          ord=read();x=read();y=read();
          if(ord==0){
             v=read();
            // add(1,n,x,y,v,root);
             Modify(1,n,x,y,v,root);

          }
          else{
              printf("%d ",Query(1,n,x,y,root));
              printf("%d ",Query2(1,n,x,y,root));
              printf("%d\n",Query3(1,n,x,y,root));
          }
    }
}

你可能感兴趣的:(模板,水题,树状数组)