正常的线段树

正常的线段树

zkw线段树的区间修改实在是不明白……

差分和前缀和的前缀和是什么gui……

还是用正常的写了一发(数据大一定要用输入输出优化,大概能节省1/4的时间)


代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

#define rep(i,x,y) for (int i=x;i<=y;i++)
#define dep(i,y,x) for (int i=y;i>=x;i--)

using namespace std;

const int maxn=200000+10;

int n,m,type,l,r,k,a[maxn],T[maxn*3],tag[maxn*3];

int build_tree(int k,int l,int r) 
{
 int mid=(l+r)>>1;
 T[k]=((l==r)?a[l]:(build_tree((k<<1),l,mid)+build_tree((k<<1)+1,mid+1,r)));
 return T[k];
}

void update(int k,int l,int r,int val)
{
 T[k]+=(r-l+1)*val;
 if (l<r) tag[k]+=val;
}

void pushdown(int k,int l,int r)
{
 int mid=(l+r)>>1;
 if (l<r) update((k<<1),l,mid,tag[k]),update((k<<1)+1,mid+1,r,tag[k]);
 tag[k]=0;
}

void add(int k,int l,int r,int x,int y,int val)
{
 if ((x<=l)&&(r<=y)) 
  update(k,l,r,val);
 else 
 {
  int mid=(l+r)>>1;
  
  if (tag[k]) pushdown(k,l,r);

  if (x<=mid) add((k<<1),l,mid,x,y,val); 
  if (y>mid) add((k<<1)+1,mid+1,r,x,y,val);

  T[k]=T[(k<<1)]+T[(k<<1)+1];
 }
}

int query(int k,int l,int r,int x,int y)
{
 if ((x<=l)&&(r<=y))
  return T[k];
 else
 {
  int mid=(l+r)>>1,ans=0;

  if (tag[k]) pushdown(k,l,r);

  if (x<=mid) ans+=query((k<<1),l,mid,x,y);
  if (y>mid) ans+=query((k<<1)+1,mid+1,r,x,y);

  T[k]=T[(k<<1)]+T[(k<<1)+1];
  return ans;
 }
}

int main()
{
 scanf("%d",&n);
 rep(i,1,n) scanf("%d",&a[i]);
 
 T[1]=build_tree(1,1,n);

 scanf("%d",&m);
 rep(i,1,m)
 {
  scanf("%d",&type);
  
  if (type==1)
  {
   scanf("%d%d%d",&l,&r,&k);
   add(1,1,n,l,r,k);
  }
  else
  {
   scanf("%d%d",&l,&r);
   printf("%d\n",query(1,1,n,l,r));
  }
 }

 return 0;
}


posted @ 2016-06-08 12:20  Krew  阅读(135)  评论(0)    收藏  举报