Visitors hit counter dreamweaver

POJ 3468 还是线段树的

     通过这道题还是又进一步对线段树有了更深的认识,加油加油!

      借郭老师的分析:

         本题树节点要存哪些信息?只存该区间的数的和,行不行?只存和,会导致每次加数的时候都要更新到叶子节点,速度太慢,这是必须要避免的。

 本题树节点结构:

                 struct node {

                            int l ,r; //区间起点和终点

                            node * pLeft, * pRight;

                            long long sum; //原来的和

                            long long inc;//增量n的累加

                                  }; //本节点区间的和实际上是sum+inc*(r-l+1)

        在增加时,如果要加的区间正好覆盖一个节点,则增加其节点的inc值,不再往下走,否则要更新sum,再将增量往下传在查询时,如果待查区间不是正好覆盖一个节点,就将   节点的inc往下带,然后将inc代表的所有增量累加到sum上后将inc清0,接下来再往下查询。

 

#include <iostream>

using namespace std;

struct node{
int l,r,mid;
long long sum; //vc下用_int64,G++下用long long.OJ上用的是G++
long long inc;
node *pLeft,*pRight;
}Node[400000];



int nCount=0;
void Create(int l,int r,node *pRoot){
pRoot->l=l;pRoot->r=r;
pRoot->sum=0;
pRoot->inc=0;
pRoot->mid=(l+r)/2;
if(l==r) return;
nCount++;
pRoot->pLeft=Node+nCount;
nCount++;
pRoot->pRight=Node+nCount;
Create(l,pRoot->mid,pRoot->pLeft);
Create(pRoot->mid+1,r,pRoot->pRight);
}

void Insert(node *pRoot,int i,int v){ //Insert and Sum.
if(i==pRoot->l && i==pRoot->r){
pRoot->sum=v;
return;
}
pRoot->sum+=v;
if(i>=pRoot->mid+1){ //不能使大于等于。想想为什么!
Insert(pRoot->pRight,i,v);
}
else{
Insert(pRoot->pLeft,i,v);
}
}

void Add(node *pRoot,int l,int r,int v){

if(pRoot->l==l && pRoot->r==r){
pRoot->inc+=v;
return;
}
pRoot->sum+=v*(r-l+1);
if(l>=pRoot->mid+1){
Add(pRoot->pRight,l,r,v);
}
else if(r<=pRoot->mid){
Add(pRoot->pLeft,l,r,v);
}
else{
Add(pRoot->pLeft,l,pRoot->mid,v);
Add(pRoot->pRight,pRoot->mid+1,r,v);
}
}
long long GetSum(int l,int r,node *pRoot){
if(pRoot->l==l && pRoot->r==r){
return pRoot->sum+(r-l+1)*pRoot->inc;
}
pRoot->sum+=(pRoot->r-pRoot->l+1)*pRoot->inc; //之前的Add()到这就满足条件,结束了。我在这被卡了好久。主要是对线段树的操作还不时很熟练。
Add(pRoot->pLeft,pRoot->l,pRoot->mid,pRoot->inc);
Add(pRoot->pRight,pRoot->mid+1,pRoot->r,pRoot->inc);
pRoot->inc=0; //到此就把inc向下推了一级
if(l>=pRoot->mid+1){
return GetSum(l,r,pRoot->pRight);
}
else if(r<=pRoot->mid){
return GetSum(l,r,pRoot->pLeft);
}
else{
return GetSum(l,pRoot->mid,pRoot->pLeft) + GetSum(pRoot->mid+1
,r,pRoot->pRight);
}
}

int main()
{
int n,q,t,x,y,z;
int i;
char c;
scanf("%d%d",&n,&q);
Create(1,n,Node);
for(i=1;i<=n;i++){
scanf("%d",&t);
Insert(Node,i,t);
}
for(i=1;i<=q;i++){
getchar();
scanf("%c",&c);
if(c=='Q'){
scanf("%d%d",&x,&y);
printf("%lld\n",GetSum(x,y,Node));
}
else{
scanf("%d%d%d",&x,&y,&z);
Add(Node,x,y,z);
}
}
return 0;
}

 

posted @ 2012-02-23 21:51  Jason Damon  阅读(296)  评论(0编辑  收藏  举报