ayout: post
title: 笛卡尔树 + 虚树
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 单调栈
hdu6305
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+50;
const ll mod=1e9+7;
int a[maxn],l[maxn],r[maxn],sz[maxn];
ll inv[maxn];
ll ans;
stack<int>s;
void dfs(int u){
sz[u]=1;
if(l[u])
dfs(l[u]),sz[u]+=sz[l[u]];
if(r[u])
dfs(r[u]),sz[u]+=sz[r[u]];
ans=ans*inv[sz[u]]%mod;
}
int main(){
inv[0]=inv[1]=1;
for(int i=2;i<=1e6;i++)
inv[i]=1LL*inv[mod%i]*(mod-mod/i)%mod;
int t;
cin>>t;
while(t--){
int n,rt;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
l[i]=r[i]=0;
while(!s.empty()&&a[i]>a[s.top()])
l[i]=s.top(),s.pop();
if(!s.empty())
r[s.top()]=i;
s.push(i);
}
while(!s.empty())
rt=s.top(),s.pop();
ans=1LL*inv[2]*n;
dfs(rt);
cout<<ans<<endl;
}
return 0;
}
2019牛客暑期多校训练营(第一场)(A)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+50;
const ll mod=1e9+7;
int l[maxn][2],r[maxn][2],rt[2];
int a[maxn],b[maxn];
stack<int>st;
bool dfs(int u){
if(l[u][0]!=l[u][1]||r[u][0]!=r[u][1])
return false;
int ok=1;
if(l[u][0])ok&=dfs(l[u][0]);
if(r[u][0])ok&=dfs(r[u][0]);
return ok;
}
bool check(int mid){
for(int i=1;i<=mid;i++){
l[i][0]=r[i][0]=0;
while(!st.empty()&&a[i]<a[st.top()]){
l[i][0]=st.top();
st.pop();
}
if(!st.empty())r[st.top()][0]=i;
st.push(i);
}
while(!st.empty())
rt[0]=st.top(),st.pop();
for(int i=1;i<=mid;i++){
l[i][1]=r[i][1]=0;
while(!st.empty()&&b[i]<b[st.top()]){
l[i][1]=st.top();
st.pop();
}
if(!st.empty())r[st.top()][1]=i;
st.push(i);
}
while(!st.empty())
rt[1]=st.top(),st.pop();
if(rt[0]!=rt[1])return 0;
return dfs(rt[0]);
}
int main(){
int n;
while(cin>>n){
for(int i=1;i<=n;i++)cin>>a[i];
for(int j=1;j<=n;j++)cin>>b[j];
int l=1,r=n,ans;
while(l<=r){
int mid=(l+r)/2;
if(check(mid)){
ans=mid;
l=mid+1;
}
else r=mid-1;
}
cout<<ans<<endl;
}
return 0;
}