序列

13 篇文章 0 订阅
2 篇文章 0 订阅

最近真的该好好反思一下,今天的题思路都是对的

但是不是写错了,就是看错了,或者想的偏了,没有看到题的重点

这道题如果没有单调递增的限制,不过就是一道简单的斜率优化

那么有了过后呢,用树状数组来满足这个限制,我们现在就是一个单点修改区间查询

每个点维护一下斜率优化时的东西,开个vector就可以了

听说这道题也可用CDQ分治做,可以再思考一下

#include<bits/stdc++.h>
using namespace std;
int tot,b[1000005],c[1000005];
int n,a[1000005],head[1000005],tail[1000005];
vector <int> vec[1000005];
long long dp[1000005],ans;
inline bool slope(int x,int y,int xx,int yy)
{
	return ((1.0*x*x+x-2*dp[x])-(1.0*y*y+y-2*dp[y]))*(xx-yy)>((1.0*xx*xx+xx-2*dp[xx])-(1.0*yy*yy+yy-2*dp[yy]))*(x-y);
}
double sl(int x,int y)
{
	return (1.0*x*x+x-2*dp[x])-(1.0*y*y+y-2*dp[y]);
}
inline long long maxx(long long x,long long y)
{
	if(x>y) return x;
	return y;
} 
inline int lowbit(int x)
{
	return x&-x;
}
inline int read()
{
	char c;int x;
	for(c=getchar();c!='-'&&(c>'9'||c<'0');c=getchar());
	if(c=='-')
	{
		x=0;
		for(c=getchar();c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
		return -x;
	}
	else 
	{
		x=c-'0';
		for(c=getchar();c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
		return x;
	}
}
inline void deal(int x,int i)
{
	while(head[x]<tail[x]&&sl(vec[x][head[x]+1],vec[x][head[x]])<=1.0*(i+i)*(vec[x][head[x]+1]-vec[x][head[x]])) head[x]++;
}
inline long long query(int x,int time)
{
	long long ans=-1ll*time*(time-1)/2+a[time];
	for(int i=x;i>=1;i-=lowbit(i))
	{
		deal(i,time);
		if(head[i]<=tail[i])
		{
			int now=vec[i][head[i]];
			ans=maxx(ans,dp[now]+a[time]-1ll*(time-now)*(time-now-1)/2);
		}
	}
	return ans;
}
inline void change(int x,int y)
{
	while(head[x]<tail[x]&&slope(vec[x][tail[x]],vec[x][tail[x]-1],y,vec[x][tail[x]]))
	tail[x]--;
	if(tail[x]+1<vec[x].size())
	vec[x][++tail[x]]=y;
	else vec[x].push_back(y),tail[x]++;
}
inline void modify(int x,int delta)
{
	for(int i=x;i<=tot;i+=lowbit(i))
	{
		change(i,delta);
	}
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
		b[i]=a[i];
	}
	sort(b+1,b+n+1);
	tot=unique(b+1,b+n+1)-b-1;
	for(int i=1;i<=tot;i++)
	tail[i]=-1;
	for(int i=1;i<=n;i++)
	c[i]=lower_bound(b+1,b+tot+1,a[i])-b;
	ans=-1ll*n*(n+1)/2;
	for(int i=1;i<=n;i++)
	{
		dp[i]=query(c[i],i);
		modify(c[i],i);
		ans=maxx(ans,dp[i]-1ll*(n-i+1)*(n-i)/2);
	}
	cout<<ans;
	return 0;
} 
/*
6
-6 -2 -2 -4 -2 -4
*/

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值