zoukankan      html  css  js  c++  java
  • 西安段素的取件最大只问题模板

    西安段素线段树的连续取件最大只连续区间最大值问题模板

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    struct node
    {
    	int sum;//总和
    	int lv;//左起最大值
    	int rv;//右起最大值
    	int mv;//中间的最大值
    };
    node t[100000];
    node null;
    int base[100000];
    void push_up(int root,int l,int m,int r)
    {
    	int _mv=0;
    	t[root].sum=t[root<<1].sum+t[root<<1|1].sum;//合并总和,至于为什么要记录介个值,下面会用到
    	t[root].lv=t[root].rv=t[root].mv=0;//归零
    	t[root].lv=max(t[root<<1].lv,t[root<<1].sum+t[root<<1|1].lv);//从左起的最大值要么是左区间的左起最大,或者是左区间的全部加上右区间的左起最大值,这里就用到了sum
    	t[root].rv=max(t[root<<1|1].rv,t[root<<1|1].sum+t[root<<1].rv);
    	t[root].mv=max(t[root<<1].mv,max(t[root<<1|1].mv,t[root<<1].rv+t[root<<1|1].lv));//中间的最大值有三种情况,1.左区间的中间最大,2.右区间的中间最大,3.将左右区间拼起来的中间前左右拓展的最大值。
    	return ;
    }
    void build(int root,int l,int r)
    {
    	if(l==r)
    	{
    		t[root].lv=t[root].mv=t[root].rv=t[root].sum=base[l];
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(root<<1,l,mid);
    	build(root<<1|1,mid+1,r);
    	push_up(root,l,mid,r);
    }
    void change(int root,int l,int r,int al,int ar,int k)//单点修改,只不过是强迫症写成立类似区间修改额样子
    {
    	if(l>ar||r<al)
    		return ;
    	if(l>=al&&r<=ar)
    	{
    		t[root].sum=t[root].lv=t[root].rv=t[root].mv=k;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	change(root<<1,l,mid,al,ar,k);
    	change(root<<1|1,mid+1,r,al,ar,k);
    	push_up(root,l,mid,r);
    	return ;
    }
    node check(int root,int l,int r,int al,int ar)
    {
    	if(l>ar||r<al)
    		return null;//自定义的空
    	if(l>=al&&r<=ar)
    		return t[root];
    	int mid=(l+r)>>1;
    	node t1=check(root<<1,l,mid,al,ar);//对于询问的合并跟push_up是一样的。
    	node t2=check(root<<1|1,mid+1,r,al,ar);
    	node res;
    	res.sum=t1.sum+t2.sum;
    	res.lv=max(t1.lv,t1.sum+t2.lv);
    	res.rv=max(t2.rv,t2.sum+t1.rv);
    	res.mv=max(t1.rv+t2.lv,max(t1.mv,t2.mv));
    	return res;
    }
    void init()
    {
    	null.sum=-0x7fffffff;
    	null.mv=-0x7fffffff;
    	null.lv=-0x7fffffff;
    	null.rv=-0x7fffffff;//不影响答案的无限小
    	return ;
    }
    int main()
    {
    	init();
    	int n,m;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    		scanf("%d",&base[i]);
    	build(1,1,n);
    	int a,b,c;
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&a,&b,&c);
    		if(a==1)
    			change(1,1,n,b,b,c);
    		else
    		{
    			node res=check(1,1,n,b,c);			
    			printf("%d
    ",max(res.lv,max(res.mv,res.rv)));
    		}
    	}
    	return 0;
    }
    //ps:因为没有数据测评,所以可能会有一些小bug,但大体框架就是介样的辣
    
  • 相关阅读:
    把一个数组 赋值给一个新数组
    上传图片时进行压缩
    input上传文件 显示进度条
    vue 后台接口返回文件流地址的下载
    时间戳转换
    JS 两个含有部分相同属性的对象如何快速给对应的key赋值
    javascript中把一个数组的内容全部赋值给另外一个数组
    微信小程序wxs如何使用
    优化内存
    解决position:fiexd相对父元素定位
  • 原文地址:https://www.cnblogs.com/Lance1ot/p/9130220.html
Copyright © 2011-2022 走看看