CF1220F Gardener Alex 题解--zhengjun

发布时间 2023-07-14 12:43:46作者: A_zjzj

发现根节点一定是 \(1\),所以考虑两边的子树深度,然后发现只需要考虑一段后缀或前缀的深度即可。

所以循环位移后,可以从中间往两边构建笛卡尔树,实时维护深度即可。

代码

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=2e5+10;
int n,a[N],ans[N];
int top,stk[N],f[N];
int main(){
	scanf("%d",&n);
	if(n==1)return puts("1 0"),0;
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	int cur=min_element(a+1,a+1+n)-a;
	rotate(a+1,a+cur,a+1+n);
	for(int i=1,x=0;i<=n;i++){
		int now=0;
		for(;top&&a[stk[top]]>a[i];top--)now=max(now+1,f[stk[top]]);
		stk[++top]=i,f[i]=now+1,x=max(x,top+now);
		ans[(cur-(n-i+1)+n)%n]=x;
	}
	rotate(a+1,a+2,a+1+n);
	memset(f,0,sizeof f);
	for(int i=n,x=top=0;i>=1;i--){
		int now=0;
		for(;top&&a[stk[top]]>a[i];top--)now=max(now+1,f[stk[top]]);
		stk[++top]=i,f[i]=now+1,x=max(x,top+now);
		int id=(cur-(n-i+1)+n)%n;
		ans[id]=max(ans[id],x);
	}
	int id=min_element(ans,ans+n)-ans;
	cout<<ans[id]<<' '<<id;
	return 0;
}