Luogu P10144 [WC/CTS2024] 水镜 题解

P10144 [WC/CTS2024] 水镜

对于任何一段连续上升的区间,我们不需要管它。对于任何一段连续下降的区间,我们只需要用 2L 减去每个数就可以化为一段连续上升的区间。因此,对于这两种区间,我们可以看作一个点。

于是,我们发现其实 2L 只会被波峰 aiai1,aiai+1 和波谷 aiai1,aiai+1 限制住。我们考虑对于每个波峰和波谷,是否存在一种方式可以走过去。

对于一个波峰 aiai1,aiai+1,我们有两种方法:

第一种,ai+12Lai+1,这样就得满足 2Lai+1>ai,即 2L>ai+ai+1

第二种,ai2Laiai+12Lai+1,这种情况下显然 ai+1>ai。但是这样就得满足 2Lai>ai1,即 2L>ai+ai1

如果 2L>ai+min(ai1,ai+1),则一定存在上述两种方法中的一种可以走过这个波峰。

对于一个波谷 aiai1,aiai+1,我们有两种方法:

第一种,ai12Lai1ai2Lai,这种情况下显然 ai>ai1。这样就得满足 2Lai<ai+1,即 2L<ai+ai+1

第二种,ai2Lai,这样就得满足 2Lai<ai1,即 2L<ai+ai1。这里不需要管对 ai+1 的影响,因为在下一个波峰中会统计。

如果 2L<ai+max(ai1,ai+1),则一定存在上述两种方法中的一种可以走过这个波谷。

对于波峰套波峰或波峰套波谷一类的情况,这样也是对的。原因是这样的限制给了每个波峰和波谷两种选择方式,套起来的两个波峰或波谷一定有一种方式可以匹配。

最后,我们发现合法的区间可以使用双指针维护。上面的这些限制可以使用 multiset 来维护,支持插入,删除,查询最值。

时间复杂度 O(nlogn),非常优秀。

#include <bits/stdc++.h>
using namespace std;
long long n,a[600000],ans=0,j=3; 
multiset<long long>b,s;
void add(long long x)
{
	if(x==n)return;
	if(a[x]>=a[x-1]&&a[x]>=a[x+1])s.insert(-a[x]-min(a[x-1],a[x+1]));
	if(a[x]<=a[x-1]&&a[x]<=a[x+1])b.insert(a[x]+max(a[x-1],a[x+1]));
}

void del(long long x)
{
	if(x==n)return;
	if(a[x]>=a[x-1]&&a[x]>=a[x+1])s.erase(s.find(-a[x]-min(a[x-1],a[x+1])));
	if(a[x]<=a[x-1]&&a[x]<=a[x+1])b.erase(b.find(a[x]+max(a[x-1],a[x+1])));
}

int main()
{
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
	add(2);
	for(int i=1;i<=n;i++)
	    {
	    	if(i!=1)del(i);
	    	while((b.empty()||s.empty()||*b.begin()>-(*s.begin()))&&j<=n)add(j),j++;
			ans+=(j-i);
		}
	printf("%lld\n",ans-n);
	return 0;
}
posted @   w9095  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示