%%%tjytjytjy的笛卡尔树做法:
设dp(l,r,Amin,Bmin)dp(l,r,Amin,Bmin)dp(l,r,Amin,Bmin)为把c[l],c[l+1],...,c[r]c[l],c[l+1],...,c[r]c[l],c[l+1],...,c[r]划到A,BA,BA,B两线程中,且划到AAA线程的数>Amin>Amin>Amin,划到BBB线程的数>Bmin>Bmin>Bmin的方案数。
我们找到ppp,满足c[p]=max{c[l],c[l+1],...,c[r]}c[p]=max\{c[l],c[l+1],...,c[r]\}c[p]=max{c[l],c[l+1],...,c[r]}。发现ppp只可能是单增栈AAA的末尾 或 单减栈BBB的开头。
-
若ppp是单增栈AAA的末尾:
那么c[p+1],c[p+2],...,c[r]c[p+1],c[p+2],...,c[r]c[p+1],c[p+2],...,c[r]一定要满足单调递减(这部分只能划到线程BBB),若满足则有dp(l,r,Amin,Bmin)←dp(l,p−1,Amin,max(Bmin,c[p+1]))dp(l,r,Amin,Bmin)\leftarrow dp(l,p-1,Amin,max(Bmin,c[p+1]))dp(l,r,Amin,Bmin)←dp(l,p−1,Amin,max(Bmin,c[p+1]))
(c[l],c[l+1],...,c[p−1]c[l],c[l+1],...,c[p-1]c[l],c[l+1],...,c[p−1]划到BBB线程的部分,要和划到BBB线程的c[p+1],c[p+2],...,c[r]c[p+1],c[p+2],...,c[r]c[p+1],c[p+2],...,c[r]接起来) -
若ppp是单减栈BBB的开头:
那么c[l],c[l+1],...,c[p−1]c[l],c[l+1],...,c[p-1]c[l],c[l+1],...,c[p−1]一定要满足单调递增(这部分只能划到线程AAA),若满足则有dp(l,r,Amin,Bmin)←dp(p+1,r,max(Amin,c[p−1]),Bmin)dp(l,r,Amin,Bmin)\leftarrow dp(p+1,r,max(Amin,c[p-1]),Bmin)dp(l,r,Amin,Bmin)←dp(p+1,r,max(Amin,c[p−1]),Bmin)
(c[p+1],c[p+2],...,c[r]c[p+1],c[p+2],...,c[r]c[p+1],c[p+2],...,c[r]划到AAA线程的部分,要和划到AAA线程的c[l],c[l+1],...,c[p−1]c[l],c[l+1],...,c[p-1]c[l],c[l+1],...,c[p−1]接起来)
用笛卡尔树实现。时间复杂度O(n)O(n)O(n)。
#include<bits/stdc++.h>
const int N=500010;
const int inf=0x7fffffff;
using namespace std;
int t,n,a[N],minn[N];
int top,sta[N],rt,ls[N],rs[N];
bool up[N],down[N];
void init(int u){if(!u) return;init(ls[u]),init(rs[u]);minn[u]=min(a[u],min(minn[ls[u]],minn[rs[u]]));up[u]=up[ls[u]]&&(!rs[u]);down[u]=down[rs[u]]&&(!ls[u]);
}
int dfs(int u,int Amin,int Bmin){if(!u) return 1;int ans=0;if(up[ls[u]]&&minn[ls[u]]>Amin&&a[u]>Bmin)ans+=dfs(rs[u],ls[u]?a[ls[u]]:Amin,Bmin);if(down[rs[u]]&&minn[rs[u]]>Bmin&&a[u]>Amin)ans+=dfs(ls[u],Amin,rs[u]?a[rs[u]]:Bmin);return ans;
}
int main(){minn[0]=inf;up[0]=down[0]=1;scanf("%d",&t);while(t--){scanf("%d",&n);int maxn=-inf;for(int i=1;i<=n;i++) {scanf("%d",&a[i]);if(a[i]>maxn) maxn=a[i],rt=i;ls[i]=rs[i]=0;}top=0;for(int i=1;i<=n;i++){while(top&&a[sta[top]]<a[i]){ls[i]=sta[top];top--;}if(top) rs[sta[top]]=i;sta[++top]=i;}init(rt);printf("%d\n",dfs(rt,-inf,-inf));}return 0;
}