列表

详情


NC14594. 珂朵莉的序列

描述

给你一个长为n的序列,有m个操作,全局加,或者查询区间最大子段和。

输入描述

第一行两个数n,m
之后一行n个数表示这个序列
之后m行,每行一个操作
1 x : 所有数都加上x
2 l r : 查询区间[l,r]内的最大子段和(可以不选数)

输出描述

对于每个2种类操作,输出一行一个数表示答案

示例1

输入:

5 7
-10 -3 -2 -4 -5
2 2 4
1 5
2 2 4
1 3
2 1 5
1 2
2 3 5

输出:

0
6
18
19

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 3861ms, 内存消耗: 291800K, 提交时间: 2019-02-02 23:41:31

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<vector>
#include<map>
#include<set>
using namespace std;
struct qq
{
    long long vl[4];
};
long long nowx;
const long long inf=(1LL<<62)-1+(1LL<<62);
struct query
{
    int flag,l,r,id;
    long long x;
    bool operator <(const query &temp)const
    {
        if(x==temp.x)
           return id<temp.id;
        return x<temp.x;
    }
};
query qy[660000];
int n,m;
long long a[330000];
long long ans[660000];
struct pp
{
    int cnt;
    long long sum;
};
pp now;
struct segment_tree
{
    int l,r,cnt;
    long long sum;
    long long delta,x;
    vector<pp>ll,rr,mm;
    int head[3];
};
segment_tree tree[1<<20];
void add(vector<pp>&ret,pp now)
{
    pp nw;
    while(ret.size()>=1)
    {
        nw=ret.back();
        if(nw.sum>=now.sum&&nw.cnt==now.cnt)
           return;
        if(nw.sum<=now.sum)
            ret.pop_back();
        else
           break;
    }
    while(ret.size()>=2)
    {
        pp a,b,c;
        a=ret[ret.size()-2];
        b=ret[ret.size()-1];
        c=now;
        double k1,k2;
        k1=(double)(a.sum-b.sum)/(double)(b.cnt-a.cnt);
        k2=(double)(b.sum-c.sum)/(double)(c.cnt-b.cnt);
        if(k1>=k2)
           ret.pop_back();
        else
           break;
    }
    ret.push_back(now);
}
void merge1(vector<pp>&ret,vector<pp>&a,vector<pp>&b)
{
    ret.clear();
    int i=0,j=0;
    while(i<a.size()&&j<b.size())
    {
         if(a[i].cnt<b[j].cnt)
         {
            add(ret,a[i]);
            i++;
         }
         else
         {
            add(ret,b[j]);
            j++;
         }
    }
    while(i<a.size())
    {
        add(ret,a[i]);
        i++;
    }
    while(j<b.size())
    {
        add(ret,b[j]);
        j++;
    }
}
void merge3(vector<pp>&ret,vector<pp>&a,vector<pp>&b)
{
    ret.clear();
    int i=0,j=0;
    double k1,k2;
    while(i<a.size()&&j<b.size())
    {
        if(i+1>=a.size())
           k1=inf;
        else
           k1=(double)(a[i].sum-a[i+1].sum)/(double)(a[i+1].cnt-a[i].cnt);
        if(j+1>=b.size())
           k2=inf;
        else
           k2=(double)(b[j].sum-b[j+1].sum)/(double)(b[j+1].cnt-b[j].cnt);
        now.cnt=a[i].cnt+b[j].cnt;
        now.sum=a[i].sum+b[j].sum;
        add(ret,now);
        if(k1<k2)
           i++;
        else
           j++;
    }
}
void merge(segment_tree &ret,segment_tree ll,segment_tree rr)
{
    int i,j,s,p,q;
    vector<pp>vec;
    vec.clear();
    ret.sum=ll.sum+rr.sum;
    ret.cnt=ll.cnt+rr.cnt;
    for(i=0;i<rr.ll.size();i++)
    {
        now.sum=rr.ll[i].sum+ll.sum;
        now.cnt=rr.ll[i].cnt+ll.cnt;
        vec.push_back(now);
    }
    merge1(ret.ll,vec,ll.ll);
    vec.clear();
    for(i=0;i<ll.rr.size();i++)
    {
        now.sum=ll.rr[i].sum+rr.sum;
        now.cnt=ll.rr[i].cnt+rr.cnt;
        vec.push_back(now);
    }
    merge1(ret.rr,vec,rr.rr);
    vec.clear();
    merge3(vec,rr.ll,ll.rr);
    merge1(ret.mm,vec,rr.mm);
    vec.clear();
    for(i=0;i<ret.mm.size();i++)
        vec.push_back(ret.mm[i]);
    merge1(ret.mm,vec,ll.mm);
}
void build(int left,int right,int id)
{
    int l=2*id+1,r=2*id+2,mid=(left+right)>>1;
    tree[id].l=left;
    tree[id].r=right;
    tree[id].delta=0;
    tree[id].ll.clear();
    tree[id].rr.clear();
    tree[id].mm.clear();
    memset(tree[id].head,0,sizeof(tree[id].head));
    if(left==right)
    {
        tree[id].sum=a[left];
        tree[id].cnt=1;
        now.cnt=now.sum=0;
        add(tree[id].ll,now);
        add(tree[id].rr,now);
        add(tree[id].mm,now);
        now.cnt=1;
        now.sum=a[left];
        add(tree[id].ll,now);
        add(tree[id].rr,now);
        add(tree[id].mm,now);
        return;
    }
    build(left,mid,l);
    build(mid+1,right,r);
    merge(tree[id],tree[l],tree[r]);
}
void reconstruct(int &head,vector<pp>&awp,long long delta)
{
    while(head+1<awp.size())
    {
        double k=(double)(awp[head].sum-awp[head+1].sum)/(double)(awp[head+1].cnt-awp[head].cnt);
        if(k<=delta)
            head++;
        else
            break;
    }
}
void zz(int id)
{
    reconstruct(tree[id].head[0],tree[id].ll,nowx);
    reconstruct(tree[id].head[1],tree[id].rr,nowx);
    reconstruct(tree[id].head[2],tree[id].mm,nowx);
}
qq qw(int left,int right,int id)
{
    int l=2*id+1,r=2*id+2;
    qq ret;
    memset(ret.vl,0,sizeof(ret.vl));
    if(tree[id].r<left||tree[id].l>right)
        return ret;
    if(tree[id].l>=left&&tree[id].r<=right)
    {
          zz(id);
         ret.vl[0]=tree[id].mm[tree[id].head[2]].sum+1LL*nowx*tree[id].mm[tree[id].head[2]].cnt;
         ret.vl[1]=tree[id].ll[tree[id].head[0]].sum+1LL*nowx*tree[id].ll[tree[id].head[0]].cnt;
         ret.vl[2]=tree[id].rr[tree[id].head[1]].sum+1LL*nowx*tree[id].rr[tree[id].head[1]].cnt;
         ret.vl[3]=tree[id].sum+1LL*tree[id].cnt*nowx;
         return ret;
    }
    qq lp,rp;
    lp=qw(left,right,l);
    rp=qw(left,right,r);
    ret.vl[0]=max(lp.vl[0],rp.vl[0]);
    ret.vl[0]=max(ret.vl[0],lp.vl[2]+rp.vl[1]);
    ret.vl[1]=max(lp.vl[1],lp.vl[3]+rp.vl[1]);
    ret.vl[2]=max(rp.vl[2],rp.vl[3]+lp.vl[2]);
    ret.vl[3]=lp.vl[3]+rp.vl[3];
    return ret;
}
int main()
{
    int i,j,s,p,q,cmft=0;
    scanf("%d%d",&n,&m);
    int x;
    for(i=0;i<n;i++)
    {
        scanf("%d",&x);
        a[i]=x;
    }
    long long delta=0;
    for(i=0;i<m;i++)
    {
        scanf("%d",&qy[i].flag);
        if(qy[i].flag==1)
        {
            scanf("%d",&x);
            qy[i].x=x;
           if(i)
              qy[i].x+=qy[i-1].x;
             
        }
        else
        {
            qy[i].id=cmft++;
            scanf("%d%d",&qy[i].l,&qy[i].r);
            qy[i].l--;
            qy[i].r--;
            if(i)
                qy[i].x=qy[i-1].x;
            else
                qy[i].x=0;
        }
    }
    sort(qy,qy+m);
    for(i=1;i<m;i++)
        qy[i].x-=qy[0].x;
    for(i=0;i<n;i++)
        a[i]+=qy[0].x;
    qy[0].x=0;
    for(i=m-1;i>0;i--)
        qy[i].x-=qy[i-1].x;
    build(0,n-1,0);
    nowx=0;
    for(i=0;i<m;i++)
    {
        nowx+=qy[i].x;
        if(qy[i].flag==2)
        {
            qq awp=qw(qy[i].l,qy[i].r,0);
            ans[qy[i].id]=awp.vl[0];
        }
    }
    for(i=0;i<cmft;i++)
       printf("%lld\n",ans[i]);
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 2749ms, 内存消耗: 291896K, 提交时间: 2018-01-06 17:23:06

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<vector>
#include<map>
#include<set>
using namespace std;
struct qq
{
	long long vl[4];
};
long long nowx;
const long long inf=(1LL<<62)-1+(1LL<<62);
struct query
{
    int flag,l,r,id;
    long long x;
    bool operator <(const query &temp)const
    {
        if(x==temp.x)
           return id<temp.id;
        return x<temp.x;
    }
};
query qy[660000];
int n,m;
long long a[330000];
long long ans[660000];
struct pp
{
    int cnt;
    long long sum;
};
pp now;
struct segment_tree
{
    int l,r,cnt;
    long long sum;
    long long delta,x;
    vector<pp>ll,rr,mm;
    int head[3];
};
segment_tree tree[1<<20];
void add(vector<pp>&ret,pp now)
{
	pp nw;
	while(ret.size()>=1)
	{
		nw=ret.back();
		if(nw.sum>=now.sum&&nw.cnt==now.cnt)
		   return;
        if(nw.sum<=now.sum)
       	    ret.pop_back();
        else
           break;
	}
	while(ret.size()>=2)
	{
		pp a,b,c;
		a=ret[ret.size()-2];
		b=ret[ret.size()-1];
		c=now;
		double k1,k2;
		k1=(double)(a.sum-b.sum)/(double)(b.cnt-a.cnt);
	    k2=(double)(b.sum-c.sum)/(double)(c.cnt-b.cnt);
	    if(k1>=k2)
	       ret.pop_back();
        else
           break;
	}
	ret.push_back(now);
}
void merge1(vector<pp>&ret,vector<pp>&a,vector<pp>&b)
{ 
    ret.clear();
    int i=0,j=0;
    while(i<a.size()&&j<b.size())
    { 
         if(a[i].cnt<b[j].cnt)
         {
            add(ret,a[i]);
            i++;
		 }
		 else
		 {
            add(ret,b[j]); 
		    j++;
		 }
	} 
	while(i<a.size())
	{
		add(ret,a[i]);
		i++;
	}
	while(j<b.size())
	{
		add(ret,b[j]);
		j++;
	} 
}
void merge3(vector<pp>&ret,vector<pp>&a,vector<pp>&b)
{
	ret.clear();
	int i=0,j=0;
	double k1,k2;
	while(i<a.size()&&j<b.size())
	{
		if(i+1>=a.size())
		   k1=inf;
        else
           k1=(double)(a[i].sum-a[i+1].sum)/(double)(a[i+1].cnt-a[i].cnt);
	    if(j+1>=b.size())
	       k2=inf;
        else
           k2=(double)(b[j].sum-b[j+1].sum)/(double)(b[j+1].cnt-b[j].cnt);
        now.cnt=a[i].cnt+b[j].cnt;
        now.sum=a[i].sum+b[j].sum;
        add(ret,now);
		if(k1<k2)
           i++;
        else
           j++;
	} 
}
void merge(segment_tree &ret,segment_tree ll,segment_tree rr)
{
    int i,j,s,p,q;
    vector<pp>vec;
    vec.clear();
    ret.sum=ll.sum+rr.sum;
    ret.cnt=ll.cnt+rr.cnt;
    for(i=0;i<rr.ll.size();i++)
    {
        now.sum=rr.ll[i].sum+ll.sum;
        now.cnt=rr.ll[i].cnt+ll.cnt;
        vec.push_back(now);
    }
    merge1(ret.ll,vec,ll.ll);
	vec.clear();
	for(i=0;i<ll.rr.size();i++)
    {
    	now.sum=ll.rr[i].sum+rr.sum;
    	now.cnt=ll.rr[i].cnt+rr.cnt;
    	vec.push_back(now);
    }
    merge1(ret.rr,vec,rr.rr);
    vec.clear();
    merge3(vec,rr.ll,ll.rr);
    merge1(ret.mm,vec,rr.mm);
    vec.clear();
    for(i=0;i<ret.mm.size();i++)
        vec.push_back(ret.mm[i]);
    merge1(ret.mm,vec,ll.mm);
}
void build(int left,int right,int id)
{
    int l=2*id+1,r=2*id+2,mid=(left+right)>>1; 
    tree[id].l=left;
    tree[id].r=right;
    tree[id].delta=0;
    tree[id].ll.clear();
    tree[id].rr.clear();
    tree[id].mm.clear();
    memset(tree[id].head,0,sizeof(tree[id].head));
    if(left==right)
    {
        tree[id].sum=a[left];
        tree[id].cnt=1;
        now.cnt=now.sum=0;
        add(tree[id].ll,now);
        add(tree[id].rr,now); 
        add(tree[id].mm,now);
        now.cnt=1;
        now.sum=a[left];
        add(tree[id].ll,now);
        add(tree[id].rr,now);
        add(tree[id].mm,now);
        return;
    }
    build(left,mid,l);
    build(mid+1,right,r);
    merge(tree[id],tree[l],tree[r]);
}
void reconstruct(int &head,vector<pp>&awp,long long delta)
{
	while(head+1<awp.size())
	{
		double k=(double)(awp[head].sum-awp[head+1].sum)/(double)(awp[head+1].cnt-awp[head].cnt);
		if(k<=delta)
			head++;
		else
		    break;
	}
}
void zz(int id)
{
	reconstruct(tree[id].head[0],tree[id].ll,nowx);
	reconstruct(tree[id].head[1],tree[id].rr,nowx);
	reconstruct(tree[id].head[2],tree[id].mm,nowx);
}
qq qw(int left,int right,int id)
{
	int l=2*id+1,r=2*id+2;
    qq ret;
    memset(ret.vl,0,sizeof(ret.vl));
	if(tree[id].r<left||tree[id].l>right)
	    return ret;
    if(tree[id].l>=left&&tree[id].r<=right)
    {
    	  zz(id);
    	 ret.vl[0]=tree[id].mm[tree[id].head[2]].sum+1LL*nowx*tree[id].mm[tree[id].head[2]].cnt;
    	 ret.vl[1]=tree[id].ll[tree[id].head[0]].sum+1LL*nowx*tree[id].ll[tree[id].head[0]].cnt;
    	 ret.vl[2]=tree[id].rr[tree[id].head[1]].sum+1LL*nowx*tree[id].rr[tree[id].head[1]].cnt;
    	 ret.vl[3]=tree[id].sum+1LL*tree[id].cnt*nowx;
    	 return ret;
    }
    qq lp,rp;
    lp=qw(left,right,l);
    rp=qw(left,right,r);
    ret.vl[0]=max(lp.vl[0],rp.vl[0]);
    ret.vl[0]=max(ret.vl[0],lp.vl[2]+rp.vl[1]);
    ret.vl[1]=max(lp.vl[1],lp.vl[3]+rp.vl[1]);
    ret.vl[2]=max(rp.vl[2],rp.vl[3]+lp.vl[2]);
    ret.vl[3]=lp.vl[3]+rp.vl[3];
    return ret;
}
int main()
{
    int i,j,s,p,q,cmft=0;
    scanf("%d%d",&n,&m);
    int x;
	for(i=0;i<n;i++)
	{
	    scanf("%d",&x);
	    a[i]=x;
	}
	long long delta=0;
	for(i=0;i<m;i++)
    {
        scanf("%d",&qy[i].flag);
        if(qy[i].flag==1)
        {
		    scanf("%d",&x);
		    qy[i].x=x;
		   if(i)
              qy[i].x+=qy[i-1].x;
            
		}
        else
        {
        	qy[i].id=cmft++;
		    scanf("%d%d",&qy[i].l,&qy[i].r);
            qy[i].l--;
            qy[i].r--;
            if(i)
                qy[i].x=qy[i-1].x;
            else
                qy[i].x=0;
        }
    }
    sort(qy,qy+m);
    for(i=1;i<m;i++)
        qy[i].x-=qy[0].x;
    for(i=0;i<n;i++)
        a[i]+=qy[0].x;
	qy[0].x=0;
    for(i=m-1;i>0;i--)
        qy[i].x-=qy[i-1].x; 
    build(0,n-1,0);
    nowx=0;
	for(i=0;i<m;i++)
    {
    	nowx+=qy[i].x; 
    	if(qy[i].flag==2)
        { 
    		qq awp=qw(qy[i].l,qy[i].r,0);
    		ans[qy[i].id]=awp.vl[0];
    	}
    }
    for(i=0;i<cmft;i++)
       printf("%lld\n",ans[i]);
	return 0;
}

上一题