5231. 【NOIP2017模拟A组模拟8.5】序列问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Larry1118/article/details/86669838

这题分治。
对于一个区间[l,r]
我们可以分三种情况讨论:
(设左端点为a,右端点为b)

1:a,b都在[l,mid]

2:a,b都在[mid+1,r]

3:a,b跨过了mid,也就是a<=mid && b>mid

1,2都可以从下一层求出,所以我们只需要求出ans即可。
而3怎么求呢?
我们设mi[],ma[],sma[],smi[],s[]
i:

l<=i<=mid

mi[i]表示[i,mid]中的最小值
ma[i]表示[i,mid]中的最大值
smi[i]表示mi[i~mid]的和
sma[i]表示ma[i~mid]的和
s[i]表示∑ma[i]*mi[i](i<=mid)

mid+1<=i<=r

同理

我们可以枚举左端点a(mid->l)
然后找到右边([mid+1,r])中第一个大于ma[a]的位置u
第一个小于mi[a]的位置v

PS:(我们可以发现,在a向左移的时候,u,v的位置是单调递增的!!!)

我们分成三块来求:(设u<v)

1:[a,u-1]

它的最大值一定是mi[a],最小值一定是ma[a],然后再乘(u-mid)

2:[u,v-1]

它的最大值就是ma[a],而最小值的话不确定,所以我们可以用smi[v]-smi[u]来求和

3:[v,r]

它的最大值和最小值都不确定!!!

but,肯定不是mid左边的!!

因为u,v已经是比那些还要有的了!!!

所以我们就要用到s[]来求就可以了,为(s[r]-s[v])
好啦,分治完后输出答案即可。

上标:

#include<cstdio>
#include<algorithm>
#define N 500010
#define mo 1000000007
#define ll long long
using namespace std;
ll a[N],smi[N],sma[N],mi[N],ma[N],s[N],ans=0;
int n;

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

void solve(int l,int r)
{
	if (l==r) {(ans+=a[l]*a[l])%=mo; return;}
	int mid=l+r>>1;
	solve(l,mid),solve(mid+1,r);
	smi[mid]=sma[mid]=ma[mid]=s[mid]=0;
	mi[mid]=1000000000;
	for (int i=mid+1;i<=r;i++)
	{
		mi[i]=min(mi[i-1],a[i]),ma[i]=max(ma[i-1],a[i]);
		smi[i]=(smi[i-1]+mi[i])%mo,sma[i]=(sma[i-1]+ma[i])%mo;
		s[i]=(s[i-1]+mi[i]*ma[i])%mo;
	}
	ll mil=1000000000,mal=0,u=mid+1,v=mid+1;
	for (int i=mid;i>=l;i--)
	{
		mil=min(mil,a[i]),mal=max(mal,a[i]);
		while (mi[u]>mil && u<=r) u++;u--;
		while (ma[v]<mal && v<=r) v++;v--;
		if (u<v)
		{
			(ans+=(u-mid)*mal%mo*mil%mo)%=mo;
			(ans+=(smi[v]-smi[u]+mo)%mo*mal%mo)%=mo;
			(ans+=s[r]-s[v])%=mo;
		}
		else
		{
			(ans+=(v-mid)*mal%mo*mil%mo)%=mo;
			(ans+=(sma[u]-sma[v]+mo)%mo*mil%mo)%=mo;
			(ans+=s[r]-s[u])%=mo;
		}
	}
}

int main()
{
	freopen("seq.in","r",stdin);
	freopen("seq.out","w",stdout);
	n=read();
	for (int i=1;i<=n;i++) a[i]=read();
	solve(1,n);
	printf("%lld\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Larry1118/article/details/86669838