zoukankan      html  css  js  c++  java
  • 解题报告:luogu P1115(模板 最大子段和)

    题目链接:P1115 最大子段和
    告诉你,这个我调了一天的题是橙题......
    线性容易得到,放篇题解:

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        int n[200001],p,ans[200001]={0};
        int sum=-9999999;//|x|<=10000   QWQ
        cin>>p;
        for(int i=1;i<=p;i++)
        {
            cin>>n[i];//输入
            ans[i]=max(ans[i-1]+n[i],n[i]);//DP
            sum=max(sum,ans[i]);//取最大值也同时进行,节约时间
        }
        cout<<sum;//直接输出
        return 0;
    }
    

    可我想到一道紫题,这样做沦为(O(n^2)),那我们如何维护任意区间的最大子段和,可以用线段树维护,开始想了个(O(n^2logn)),显然是假的,然后学了下,又出了些(SB)错误,终于(AC)了。

    (Code):

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int MAXN=200005;
    int t[MAXN],n;
    struct seg_t
    {
    	int l,r,sum,pre,suf,maxn;
    	seg_t()
    	{
    		l=r=sum=pre=suf=maxn=0;
    	}
    }a[MAXN<<2];
    void update(int k)
    {
    	a[k].pre=max(a[k<<1].pre,a[k<<1].sum+a[k<<1|1].pre);
    	a[k].suf=max(a[k<<1|1].suf,a[k<<1|1].sum+a[k<<1].suf);
    	a[k].maxn=max(max(a[k<<1].maxn,a[k<<1|1].maxn),a[k<<1].suf+a[k<<1|1].pre);
    	a[k].sum=a[k<<1].sum+a[k<<1|1].sum;
    }
    void build(int k,int l,int r)
    {
    	a[k].l=l,a[k].r=r;
    	if(l==r)
    	{
    		a[k].maxn=a[k].sum=a[k].suf=a[k].pre=t[l];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(k<<1,l,mid),build(k<<1|1,mid+1,r); 
    	update(k);
    }
    seg_t query(int k,int l,int r)
    {
    	int mid=(a[k].l+a[k].r)>>1;
    	if(a[k].l==l&&a[k].r==r) return a[k];
    	if(r<=mid) return query(k<<1,l,r);
    	else if(l>=mid+1) return query(k<<1|1,l,r);
    	else
    	{
    		seg_t ll,rr,ans;
    		ll=query(k<<1,l,mid),rr=query(k<<1|1,mid+1,r);
    		ans.sum=ll.sum+rr.sum;
    		ans.maxn=max(ll.maxn,rr.maxn);
    		ans.pre=max(ll.pre,ll.sum+rr.pre);
    		ans.suf=max(rr.suf,rr.sum+ll.suf);
    		ans.maxn=max(ans.maxn,ll.suf+rr.pre);
    		return ans;
    	}
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d",&t[i]);
    	build(1,1,n);
    	printf("%d
    ",query(1,1,n).maxn);
    	return 0;
    }
    

    这种线段树咱真没见过

  • 相关阅读:
    sklearn.neighbors.KNeighborsClassifier的k-近邻算法使用介绍
    修改或定义sudo下的PATH环境变量
    Linux安装deb后缀包
    Linux截图软件shutter安装
    Python变量前'*'和'**'的作用
    线段树入门
    机器学习实战源码&数据集
    Spring Boot 自动配置原理(精髓)
    Spring Boot 注解配置 day03
    Spring Boot 配置_yaml语法介绍 day02
  • 原文地址:https://www.cnblogs.com/tlx-blog/p/12317997.html
Copyright © 2011-2022 走看看