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;
}
我是一名在校大学生,热爱编程,虽然起步晚了些,但我会努力的。呵呵!
数据结构 算法