首页 > 其他分享 >AT_abc248_h [ABC248Ex] Beautiful Subsequences 题解

AT_abc248_h [ABC248Ex] Beautiful Subsequences 题解

时间:2025-01-10 20:44:43浏览次数:1  
标签:Beautiful suf limits min int 题解 mid max abc248

题目传送门

前置知识

树状数组 | 序列分治

解法

考虑序列分治,设因 \(\max\) 和 \(\min\) 形成的分节点先后为 \(k_{1},k_{2}\)。

对于 \(j \in (mid,k_{1}]\),等价于统计满足 \(\max\limits_{h=i}^{mid} \{ a_{h} \}-\min\limits_{h=i}^{mid} \{ a_{h} \} \le j-i+k\) 的 \(j\) 的数量,容易求解。

对于 \(j \in (k_{1},k_{2}]\),以 \([i,j]\) 的 \(\max\) 落在 \((k_{1},k_{2}]\) 为例,需要统计满足 \(\max\limits_{h=mid+1}^{j} \{ a_{h} \}-\min\limits_{h=i}^{mid} \{ a_{h} \} \le j-i+k\) 的 \(j\) 数量,移项得到 \(\max\limits_{h=mid+1}^{j} \{ a_{h} \}-j \le \min\limits_{h=i}^{mid} \{ a_{h} \}-i+k\),移动指针的过程中树状数组维护 \(\max\limits_{h=mid+1}^{j} \{ a_{h} \}-j\) 的桶数组即可。

对于 \(j \in (k_{2},r]\),需要统计 \(\max\limits_{h=mid+1}^{j} \{ a_{h} \}-\min\limits_{h=mid+1}^{j} \{ a_{h} \} \le j-i+k\) 的 \(j\) 数量,移项得到 \(\max\limits_{h=mid+1}^{j} \{ a_{h} \}-\min\limits_{h=mid+1}^{j} \{ a_{h} \}-j \le -i+k\),移动指针的过程中树状数组维护 \(\max\limits_{h=mid+1}^{j} \{ a_{h} \}-\min\limits_{h=mid+1}^{j} \{ a_{h} \}-j\) 的桶数组即可。

注意下标移位。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
int a[140010],pre_max[140010],pre_min[140010],n,m;
ll ans=0;
struct BIT
{
	int c[500010];
	int lowbit(int x)
	{
		return (x&(-x));
	}
	void add(int n,int x,int val)
	{
		for(int i=x;i<=n;i+=lowbit(i))
		{
			c[i]+=val;
		}
	}
	void del(int n,int x)
	{
		for(int i=x;i<=n;i+=lowbit(i))
		{
			c[i]=0;
		}
	}
	int getsum(int x)
	{
		int ans=0;
		for(int i=x;i>=1;i-=lowbit(i))
		{
			ans+=c[i];
		}
		return ans;
	}
}T[3];
void solve(int l,int r)
{
	if(l==r)
	{
		ans++;
		return;
	}
	int mid=(l+r)/2,suf_max=0,suf_min=0x7f7f7f7f;
	pre_max[mid+1]=pre_min[mid+1]=a[mid+1];
	for(int i=mid+2;i<=r;i++)
	{
		pre_max[i]=max(pre_max[i-1],a[i]);  pre_min[i]=min(pre_min[i-1],a[i]);
	}
	for(int i=mid+1;i<=r;i++)  T[0].add(500000,pre_max[i]-pre_min[i]-i+300000,1);
	for(int i=mid,k1=mid,k2=mid;i>=l;i--)
	{
		suf_max=max(suf_max,a[i]);  suf_min=min(suf_min,a[i]);
		while(k1+1<=r&&suf_max>=pre_max[k1+1]&&suf_min<=pre_min[k1+1])
		{
			k1++;
			T[1].add(500000,pre_max[k1]-k1+300000,-1);
			T[2].add(500000,-k1-pre_min[k1]+300000,-1);
		}
		while(k2+1<=r&&(suf_max>=pre_max[k2+1]||suf_min<=pre_min[k2+1]))
		{
			k2++;
			T[0].add(500000,pre_max[k2]-pre_min[k2]-k2+300000,-1);
			T[1].add(500000,pre_max[k2]-k2+300000,1);
			T[2].add(500000,-k2-pre_min[k2]+300000,1);
		}
		ans+=max(0,k1-max(mid+1,suf_max-suf_min-m+i)+1);
		ans+=T[0].getsum(m-i+300000);
		ans+=(suf_min<=pre_min[k2])?T[1].getsum(suf_min-i+m+300000):T[2].getsum(-suf_max-i+m+300000);
	}
	for(int i=mid+1;i<=r;i++)  T[0].del(500000,pre_max[i]-pre_min[i]-i+300000);
	for(int i=mid+1;i<=r;i++)  T[1].del(500000,pre_max[i]-i+300000);
	for(int i=mid+1;i<=r;i++)  T[2].del(500000,-i-pre_min[i]+300000);
	solve(l,mid);
	solve(mid+1,r);
}
int main()
{
// #define Isaac
#ifdef Isaac
	freopen("in.in","r",stdin);
	freopen("out.out","w",stdout);
#endif
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	solve(1,n);
	cout<<ans<<endl;
	return 0;
}

标签:Beautiful,suf,limits,min,int,题解,mid,max,abc248
From: https://www.cnblogs.com/The-Shadow-Dragon/p/18664677

相关文章

  • 题解:CF1031F Familiar Operations
    传送门Solution之前有遇到类似的题,第一步先考虑转化操作和问题。对于每个数质因数分解成\(\prod{p_i^{\alpha_i}}\),我们所需要的只有\(\alpha_i\),因为只要求因子个数相同。记其为\(S_i=\{\alpha_1,\alpha_2,\dots,\alpha_k\}\),其中\(\alpha_1\geq\alpha_2\geq\dots......
  • Atcoder ABC329E Stamp 题解 [ 绿 ] [ 线性 dp ]
    Stamp:难点主要在dp转移的细节与分讨上,但通过改变状态设计可以大大简化分讨细节的题。观察首先要有一个观察:只要某一个前缀能被覆盖出来,那么无论它后面多出来多少,后面的字符串都可以帮他重新覆盖回去。这也就是dp为啥没有后效性的原因。除此之外,还要注意一个字符串不仅能在......
  • 跟我一起学 Python 数据处理(二十六):PDF 数据提取技巧与问题解决策略
    跟我一起学Python数据处理(二十六):PDF数据提取技巧与问题解决策略在Python数据处理的学习之旅中,我们已经走过了不少路程,今天继续深入探索PDF文件处理的核心技巧与方法,旨在帮助大家进一步提升数据处理能力,解决实际工作中遇到的难题。一、slate库处理PDF文件的深入......
  • D. Smithing Skill 和 D. Grid Puzzle的题解
    D.SmithingSkill:https://codeforces.com/problemset/problem/1989/D思路:https://blog.csdn.net/weixin_73936404/article/details/140045020(看这位的博客吧,这个本人第一次写卡住了,题解就当复盘了)贪心:优先消耗值小的(花费和返回的差值)且门槛小的。代码:#include<bits/stdc......
  • [NOI2018] 你的名字的题解
    [NOI2018]你的名字Solution:考虑一下\(l=1,r=\left|S\right|\)的时候怎么做,其实比较简单,我们对\(S,T\)都建立出SAM,利用这个求得\(p_i\),表示\(T_{i-p_i+1,i}\)在\(S\)上是一个连续子串,设\(fir_i\)表示\(T\)的SAM中,节点\(i\)代表的\(endpos\)中的最小值(事实上......
  • 一些比赛的题解
    A把第二个字符串反转,然后对于第一个字符串中为#的位置,输出第二个字符串中对应位置的字符即可。B考虑枚举答案(需要注意不能二分),假设当前枚举的答案为\(res\),只需考虑怎么判定该答案是否合法。不难发现,找到\(res\)的不同的两个倍数同时属于这个区间,\(res\)就是合法的。C......
  • G. D-Function 题解 (快速幂, 组合数学)
    原题链接:https://codeforces.com/contest/1985/problem/G题目:思路:要满足D(kn)==kD(n),k与n的每一位相乘都不能发生进位,k只能是一位数。考虑n的位数可能有1e9,所以用到了快速幂。代码:#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintmod......
  • 学校月考题解 #2
    一些闲话期末考,依旧是AK。题解T1有\(n\)个位置。起初每个位置都被封锁。你可以进行以下两种类型的操作:选择一个位置\(i\),其中\(1\leqi\leqn\),然后解除该位置的封锁;选择一对位置\(l\)和\(r\),其中\(1\leql\leqr\leqn\),满足位置\(l\)和\(r\)都已解除封锁,......
  • [BZOJ3159] 决战 题解
    个人感觉各方面难度高于《在美妙的数学王国中畅游》,也不知道是不是求导的关系,这题\(luogu\)难度评级还更低。不过感觉这题作完对\(LCT\)理解更顺畅了。前四个操作简单,关键在第五人格操作。注意力惊人的注意到我们无法像普通\(Splay\)一样,直接对\(LCT\)中的\(Splay\)......
  • Kubernetes集群运维生产常见问题解析与解决方案
    前言:在Kubernetes集群的日常运维工作中,我们难免会遇到各种各样的问题。这些问题可能涉及到集群的部署、配置、监控、性能优化等多个方面。为了解决这些问题,我们需要不断地学习和积累经验。在这里,我打算收集并整理一些网友曾经提出的问题,并提供相应的解析和解决方案,之前的问题无从......