• 【线段树】序列问题/Can you answer on these queries III


    Description

    给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:

    1、“1 x y”,查询区间 [x,y] 中的最大连续子段和。

    2、“2 x y”,把 A[x] 改成 y。对于每个查询指令,输出一个整数表示答案。

    Input

    第一行两个整数N,M。

    第二行N个整数A[i]。

    接下来M行每行3个整数k,x,y,k=1表示查询(此时如果x>y,请交换x,y),k=2表示修改。

    数据范围

    N ≤ 500000,M ≤ 100000

    Output

    对于每个查询指令输出一个整数表示答案。

    每个答案占一行。

    Sample Input

    5 3
    1 2 -3 4 5
    1 2 3
    2 2 -1
    1 3 2

    Sample Output

    2
    -1


    思路

    • 线段树维护:区间紧靠左右两端的最大连续子段和,区间的总和,区间跨左右子树的最大连续子段和
    • 当前区间的lmax=左子树lmax和或左子树区间和+右子树lmax(rmax同理)
    • 极小值-inf注意不能过小,溢出坑死人

    代码

    #include <iostream>
    #include <cstdio>
    #define maxn 500005
    #define inf 1005
    using namespace std;
    int n,m,v[maxn];
    struct fdfdfd{int l,r,lmax,rmax,amax,sum;}a[maxn<<2];
    void pushup(int x)
    {
    	a[x].sum=a[x<<1].sum+a[x<<1|1].sum;
    	a[x].lmax=max(a[x<<1].lmax,a[x<<1].sum+a[x<<1|1].lmax);
    	a[x].rmax=max(a[x<<1|1].rmax,a[x<<1|1].sum+a[x<<1].rmax);
    	a[x].amax=max(max(a[x<<1].amax,a[x<<1|1].amax),a[x<<1].rmax+a[x<<1|1].lmax);
    }
    void build(int x,int left,int right)
    {
    	a[x].l=left; a[x].r=right;
    	if(left==right)
    	{
    		a[x].lmax=a[x].rmax=a[x].amax=a[x].sum=v[left];
    		return;
    	}
    	int mid=(left+right)>>1;
    	build(x<<1,left,mid); build(x<<1|1,mid+1,right);
    	pushup(x);
    }
    void modify(int x,int u,int d)
    {
    	if(a[x].r<u||a[x].l>u) return;
    	if(a[x].l==u&&a[x].r==u)
    	{
    		a[x].lmax=a[x].rmax=a[x].amax=a[x].sum=d;
    		return;
    	}
    	modify(x<<1,u,d); modify(x<<1|1,u,d);
    	pushup(x);
    }
    fdfdfd query(int x,int left,int right)
    {
    	if(a[x].r<left||a[x].l>right) return (fdfdfd){0,0,-inf,-inf,-inf,-inf};
    	if(left<=a[x].l&&right>=a[x].r) return a[x];
    	fdfdfd temp1=query(x<<1,left,right),temp2=query(x<<1|1,left,right),temp;
    	temp.sum=temp1.sum+temp2.sum;
    	temp.lmax=max(temp1.lmax,temp1.sum+temp2.lmax);
    	temp.rmax=max(temp2.rmax,temp2.sum+temp1.rmax);
    	temp.amax=max(max(temp1.amax,temp2.amax),temp1.rmax+temp2.lmax);
    	return temp;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i) scanf("%d",&v[i]);
    	build(1,1,n);
    	while(m--)
    	{
    		int f1,f2,f3; scanf("%d%d%d",&f1,&f2,&f3);
    		if(f1==1)
    		{
    			if(f2>f3) swap(f2,f3);
    			printf("%d
    ",query(1,f2,f3).amax);
    		}
    		else modify(1,f2,f3);
    	}
    	return 0;
    }
    
  • 相关阅读:
    java学习日记-------------------------------------贪吃蛇
    java学习日记----------------为窗口添加背景图
    java学习日记-----------------------------弹弹球
    java学习日记----------------------封装的日期类MyDate
    java 学习日记---------简易学生信息管理系统
    第九次作业
    第八次作业
    第七次作业
    第六次作业
    第五次作业
  • 原文地址:https://www.cnblogs.com/wuwendongxi/p/13427093.html
Copyright © 2020-2023  润新知