1 条题解
-
0
自动搬运
来自洛谷,原作者为

Rigel
苍山负雪,明烛天南。|| 高二现役 OIer。搬运于
2025-08-24 23:02:10,当前版本为作者最后更新于2024-08-18 09:08:15,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
思路
在一个排序后为等差数列的数列中,定义 为数列长度, 为可能的数列公差。
试分析以 为断点形成的 个排序后为等差数列的数列中 与 的关系。
先定义 为“特殊的”,当且仅当 $l=\begin{cases} \lfloor\frac{n}{2}\rfloor\ 或\ \lfloor\frac{n}{2}\rfloor+1&n=2x+1,\ x\in\mathbb{N+},\\ \frac{n}{2}&n=2x,\ x\in\mathbb{N+}. \end{cases}$
存在如下 种情况:
-
当 时,。
-
当 时,$d=\begin{cases} 1\ 或\ 2& l\ 为“特殊的”,\\ 1 & \mathop{\operatorname{otherwise}}.\\ \end{cases}$
再定义 $\mathop{f_i}\limits_{i \in [1,n]}=[\ [p_1,p_2,\cdots,p_i] 为等差数列]$,$\mathop{g_i}\limits_{i \in [1,n]}=[\ [p_{i},p_{i+1},\cdots,p_n]为等差数列]$。
注意到,,,则 合法,因此求出 与 即可。
下面以求出 为例,此时 。
正难则反,我们设出 的值并检验 的合法性,若 合法,则 。
显然, 时 ,不再赘述。
当 时,
-
先设 。若 $l=\mathop{\operatorname{max}}(p_1,p_2,\cdots,p_i)-\mathop{\operatorname{min}}(p_1,p_2,\cdots,p_i)+1$,则 合法。
-
若 为“特殊的”,再设 ,此时遍历数列 判断 的合法性(详情见代码)。
不难发现,求 的过程中,“遍历数列”的操作至多进行 次,
不会爆时间。求 时,,过程同理,注意顺序。
代码
#include<bits/stdc++.h> #define int long long #define INF 0x7fffffffffffffff #define _max(a,b) ((a)>(b)?(a):(b)) #define _min(a,b) ((a)<(b)?(a):(b)) #define maxn 2000010 using namespace std; int t,n,a[maxn],vis[maxn],f[maxn],g[maxn],ans; inline int read(){ int ret=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+(ch&15),ch=getchar(); return ret*f; } signed main(){ t=read(); while(t--){ n=read(),ans=0; for(int i=1;i<=n;i++)a[i]=read(),vis[i]=0; if(n==1){printf("0\n");continue;} //求 f[i] int cnt=0,minn=INF,mx=-INF; for(int i=1;i<=n;i++){ vis[a[i]]=1; if(a[i]>=mx)mx=a[i]; if(a[i]<=minn)minn=a[i]; if(mx-minn+1==i||i<=2){f[i]=1;continue;} if(((n&1)&&(i==(n>>1)||i==(n>>1)+1))||(!(n&1)&&(i==(n>>1)))){ int k=((mx-minn)>>1)+1; if(k!=i){f[i]=0;continue;} int op=0; for(int j=minn;j<=mx;j+=2)if(!vis[j]){op=1;break;} f[i]=op^1; }else f[i]=0; } //求 g[i] cnt=0,minn=INF,mx=-INF; for(int i=1;i<=n;i++)vis[i]=0; for(int i=n;i>=1;i--){ vis[a[i]]=1; if(a[i]>=mx)mx=a[i]; if(a[i]<=minn)minn=a[i]; if(mx-minn+1==(n-i+1)||(n-i+1)<=2){g[i]=1;continue;} if(((n&1)&&((n-i+1)==(n>>1)||(n-i+1)==(n>>1)+1))||(!(n&1)&&(n-i+1)==(n>>1))){ int k=((mx-minn)>>1)+1; if(k!=(n-i+1)){g[i]=0;continue;} int op=0; for(int j=minn;j<=mx;j+=2)if(!vis[j]){op=1;break;} g[i]=op^1; }else g[i]=0; } for(int i=1;i<=n-1;i++)if(f[i]&&g[i+1])ans++; printf("%lld\n",ans); } return 0; } -
- 1
信息
- ID
- 10652
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者