动态最大连续和 cdoj uvalive la 【线段树】

此版本有更新操作 la3938 只是查询而已所以la3938可以上dp

但是有更新操作就上不了了

为嘛? 因为

DP 插入 O(1) 扫描O(n) 和 为O(n)

segment tree 插入O(logn) 扫描 O(logn) 和 为O(2*logn)  

化简一下 可以发现 DP(2^n) > >   segment tree(n*n)

#include<cstdio> 
#include<cstring>
#include<algorithm>
#define N 200009
using namespace std;
struct node//如果是uvalive 3938那就加一个 maxl,maxr用来记录maxi的范围 在pushup刷新这两个值 query也记得刷一下 
{
	int maxi,lmax,rmax,sum;
} tree[4*N];

void pushup(int rt)//刷新rt节点的数据 相当于lrj的minv 
{
	tree[rt].sum=tree[rt*2].sum+tree[rt*2+1].sum;
	tree[rt].maxi=max(tree[rt*2].maxi,max(tree[rt*2+1].maxi,tree[rt*2].rmax+tree[rt*2+1].lmax));
	tree[rt].lmax=max(tree[rt*2].lmax,tree[rt*2].sum+tree[rt*2+1].lmax);
	tree[rt].rmax=max(tree[rt*2+1].rmax,tree[rt*2+1].sum+tree[rt*2].rmax);		
}

void init_tree(int l,int r,int rt)
{
	if(l==r)
	{
		scanf("%d",&tree[rt].sum);
		tree[rt].maxi=tree[rt].rmax=tree[rt].lmax=tree[rt].sum;
		return;
	}	
	int mid=(r+l)/2;		
	init_tree(l,mid,rt*2);			
	init_tree(mid+1,r,rt*2+1);		
	pushup(rt);
	
}

void updata(int l,int r,int value,int position,int rt)
{
	int mid=(r+l)/2;
	if(l==r) 
	{
		tree[rt].maxi=tree[rt].rmax=tree[rt].lmax=tree[rt].sum=value;
		return;
	}
	else
	{
		if(position<=mid)//根据位置确定递归方向 
		{
			updata(l,mid,value,position,rt*2);
		}
		else
		{
			updata(mid+1,r,value,position,rt*2+1);
		}
		pushup(rt);
	}
}

node query(int l,int r,int aa,int bb,int rt)
{
	int mid=(l+r)/2;
	if(aa<=l&&bb>=r) 
	{
		return tree[rt];
	}/*为了个毛线段树的搜索为logn? 原因出在这里, 当被搜索树节点的区间被查询范围覆盖时,直接return,不必完整展开下面的
	子树(节点)*/ 
	node ka,kb,res;
	int flaga=0,flagb=0;
	if(aa<=mid)
	{
		ka=query(l,mid,aa,bb,rt*2);//分割子树(砍一半) 左 (查询左端点小于中值) 
		flaga=1;
	}
	if(bb>mid)
	{
		kb=query(mid+1,r,aa,bb,rt*2+1);// 分割子树(砍一半)右(查询右端点大于中值) 
		flagb=1;
	}
	if(flaga&&flagb)//此st节点的左右都查了 合并结果 
	{
		res.sum=ka.sum+kb.sum;
		res.lmax=max(ka.lmax,ka.sum+kb.lmax);
		res.rmax=max(kb.rmax,kb.sum+ka.rmax);
		res.maxi=max(ka.maxi,max(kb.maxi,ka.rmax+kb.lmax));
	}
	else
	{
		if(flaga)//st节点只有左子树 
		res=ka;
		if(flagb)//st节点只有右子树 
		res=kb;
	}
	return res;	
}

int main()
{
	int n,m,op,aa,bb;
	while(~scanf("%d%d",&n,&m))
	{
		init_tree(1,n,1);
		/*for(int i=1;i<=n;i++)
		printf("%d\n",tree[i].maxi);*/
		while(m--)
		{
			scanf("%d%d%d",&op,&aa,&bb);
			if(op==1)
			{
				node res=query(1,n,aa,bb,1);
				printf("%d\n",res.maxi);
			}
			else	
			{
				updata(1,n,bb,aa,1);
				/*for(int i=1;i<=n;i++)
				printf("%d\n",tree[i].maxi);
				*/
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41544329/article/details/82831019