您的位置:首页 > 理论基础 > 数据结构算法

POJ3468(线段树+延迟更新)

2013-06-04 08:43 211 查看
A Simple Problem with Integers

Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 43776 Accepted: 12806
Case Time Limit: 2000MS
Description

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

 

//线段树的延迟更新,不然每次都操作到具体叶节点会耗费大量的时间!此题用add标记每个节点有无操作,不必每次都搜索至叶节点,从而节省大量的时间!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define MAX 100003
typedef __int64 ll;
ll da[MAX],ans;
struct node
{
ll left,right,add;
ll sum;
}tree[MAX*4];
//建立以left,right为左右边界,将数组a中元素存储在首地址从1开始的tree数组中
void build( ll id, ll left, ll right )
{
tree[id].add=0;
tree[id].left = left;
tree[id].right = right;
if( left == right )
{
tree[id].sum = da[left];
return ;
}
else
{
ll mid = ( left + right )>>1;
build( id <<1, left, mid );
build( id<<1|1, mid + 1, right );
tree[id].sum = tree[id<<1].sum + tree[id<<1|1].sum;
}
}
//修改
void updata( ll id, ll left, ll right, ll adi)
{
if(tree[id].left==left&&tree[id].right==right)
{
tree[id].add+=adi;
return ;
}
else
{
if(tree[id].add!=0)
{
tree[id].sum+=(tree[id].right-tree[id].left+1)*tree[id].add;
tree[id<<1].add+=tree[id].add;
tree[id<<1|1].add+=tree[id].add;
tree[id].add=0;
}
tree[id].sum+=( right-left+1)*adi;

ll mid=(tree[id].left+tree[id].right)>>1;
if(right<=mid)
updata(id<<1,left,right,adi);
else if(left>mid)
updata(id<<1|1,left,right,adi);
else
{
updata(id<<1,left,mid,adi);
updata(id<<1|1,mid+1,right,adi);
}
}
}
//3.查询
//*****************************************************************
void query(ll id, ll left, ll right)
{
if( tree[id].left==left&&tree[id].right== right)
{
if(tree[id].add==0)
{
ans+=tree[id].sum;
return ;
}
else
{
ans+=tree[id].sum+(tree[id].right-tree[id].left+1)*tree[id].add;
return ;
}
}
else
{
if(tree[id].add!=0)
{
tree[id].sum+=(tree[id].right-tree[id].left+1)*tree[id].add;
tree[id<<1].add+=tree[id].add;
tree[(id<<1)+1].add+=tree[id].add;
tree[id].add=0;

}
ll mid = (tree[id].left+tree[id].right)>>1;
if(right<= mid )
query( id <<1, left,right);
else if(left>mid  )
query( (id <<1)+ 1,left, right);
else
{
query( id <<1,  left,mid);
query( (id<<1) + 1, mid+1,right );
}
}
}
int main()
{
ll n,i,m;
scanf("%I64d%I64d",&n,&m);
//while(~scanf("%d%d",&n,&m))
// {
for(i=1;i<=n;i++)
scanf("%I64d",&da[i]);

build(1,1,n);
for(i=0;i<m;i++)
{
ll a,b,c;
char op;
scanf(" %c",&op);
if(op=='C')
{
scanf("%I64d%I64d%I64d",&a,&b,&c);
updata(1,a,b,c);
}
else if(op=='Q')
{
ans=0;
scanf("%I64d%I64d",&a,&b);
query(1, a,b);
printf("%I64d\n",ans);
}
}
//}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息