您的位置:首页 > 其它

poj4047(线段树+延迟更新)

2013-06-04 13:14 218 查看
//线段树延迟更新

//将连续相邻的k个数据的和看成一个元素,建立线段树;交换、替代两种操作都可以统一成加法操作

 

//-------加法

//若当前加法操作的区间和当前所在节点的左右区间相同,则只修改延迟标记adi,和当前区间的最大值sum;若不一致,才开始向下执行加法操作,同时修改最大值

 

//------查询

//若当前查询的区间和当前所在区间相同,则直接返回结果;若不一致,则向下执行加法操作,同时修改最大值

 

 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
using namespace std;
#define MAX 200009
typedef  int ll;

int min(int a,int b)
{
return a<b?a:b;
}

int max(int a,int b)
{
return a<b?b:a;
}

ll a[MAX],da[MAX],ans;
struct node
{
ll left,right,add;
ll sum;
}tree[MAX*5];

//*****************************************************
//建立以left,right为左右边界,将数组da中元素存储在首地址从1开始的tree数组中

int 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 tree[id].sum;
}
else
{
ll mid = ( left + right )>>1;
tree[id].sum=max(build( id <<1, left, mid ), build( id<<1|1, mid + 1, right ));
return tree[id].sum;
}
}
//*****************************************************************

void down(int id)
{
if(tree[id].left==tree[id].right)
return ;
tree[id<<1].add+=tree[id].add;
tree[id<<1|1].add+=tree[id].add;
tree[id<<1].sum+=tree[id].add;
tree[id<<1|1].sum+=tree[id].add;
tree[id].add=0;
}

//修改
//****************************************************
//对区间[left,right]内每个元素进行加adi操作
void updata( ll id, ll left, ll right, ll adi)
{
if(tree[id].left==left&&tree[id].right==right)
{
tree[id].add+=adi;
tree[id].sum+=adi;
return ;
}
else
{
if(tree[id].add!=0)
{
down(id);
}

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);
}
if(tree[id].left!=tree[id].right)
tree[id].sum=max(tree[id<<1].sum ,tree[id<<1|1].sum);
}
}
//*****************************************************************

//3.查询
//*****************************************************
//查询区间[left,right]的和
int query(ll id, ll left, ll right)
{
if( tree[id].left==left&&tree[id].right== right)
{
return tree[id].sum;
}
else
{
if(tree[id].add!=0)
{
down(id);
}
ll mid = (tree[id].left+tree[id].right)>>1;
if(right<= mid )
return query( id <<1, left,right);
else if(left>mid  )
return query( id <<1|1,left, right);
return max( query( id <<1, left,mid) ,query( id<<1|1, mid+1,right ));
}
}
//*****************************************************************

int main()
{
int n,m,k,i,j,t;
cin>>t;
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
da[i]=0;
}

for(i=1;i<=k;i++)
da[1]+=a[i];
for(i=2;i<=n-k+1;i++)
da[i]=da[i-1]-a[i-1]+a[i+k-1];

build(1,1,n-k+1);
for(i=0;i<m;i++)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(0==op)//x处用y替换
{
updata(1,max(1,x-k+1),min(n-k+1,x),y-a[x]);
a[x]=y;
}
else if(1==op)//将x处和y处元素交换
{
if(x==y)
continue;
updata(1,max(1,x-k+1),min(n-k+1,x),a[y]-a[x]);
updata(1,max(1,y-k+1),min(n-k+1,y),a[x]-a[y]);
int temp=a[x];
a[x]=a[y];
a[y]=temp;
}
else if(2==op)//输出[x,y]区间中
{
ans=query(1,x,y-k+1);//min(y-k+1,n-k+1));
printf("%d\n",ans);
}
}
}
return 0;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树 延迟更新