如果一个节点是$0$但它子树内有$1$那么无解,否则我们只需把那些是$1$但子树内没有其他$1$的节点(这些区间是被定位的区间)都访问一遍即可
根据ZKW线段树定位区间的过程,可以发现一段(从左到右)连续的右儿子+左儿子序列确定了一个区间
所以对每个右儿子$[l,r]$,连$[0,\infty)$向$[r+1,x]$的节点,对每个左儿子$[l,r]$,连$[0,+\infty)$向$[r+1,x]$的左儿子,再对那些被定位到的点拆点连$[1,\infty)$,跑最小流即可
但这样边数太多,考虑优化,建$n$个附加点,对于左儿子$[l,r]$,从附加点$l$连向它再连向附加点$r+1$,但这样会产生左儿子连到右儿子这种不合法情况,所以对左儿子和右儿子分别建$n$个附加点即可
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int inf=2147483647;
int h[24010],nex[128010],to[128010],cap[128010],M=1,S,T;
void ins(int a,int b,int c){
M++;
to[M]=b;
cap[M]=c;
nex[M]=h[a];
h[a]=M;
}
void add(int a,int b,int c){
ins(a,b,c);
ins(b,a,0);
}
int dis[24010],q[24010];
bool bfs(){
int head,tail,x,i;
memset(dis,-1,sizeof(dis));
head=tail=1;
q[1]=S;
dis[S]=0;
while(head<=tail){
x=q[head++];
for(i=h[x];i;i=nex[i]){
if(cap[i]&&dis[to[i]]==-1){
dis[to[i]]=dis[x]+1;
if(to[i]==T)return 1;
q[++tail]=to[i];
}
}
}
return 0;
}
int cur[24010];
int dfs(int x,int flow){
if(x==T)return flow;
int us=0,i,t;
for(i=cur[x];i&&flow;i=nex[i]){
if(cap[i]&&dis[to[i]]==dis[x]+1){
t=dfs(to[i],min(flow,cap[i]));
cap[i]-=t;
cap[i^1]+=t;
us+=t;
flow-=t;
if(cap[i])cur[x]=i;
}
}
if(us==0)dis[x]=-1;
return us;
}
int dicnic(){
int ans=0;
while(bfs()){
memcpy(cur,h,sizeof(h));
ans+=dfs(S,inf);
}
return ans;
}
void add(int a,int b,int l,int r){
if(l){
add(S,b,l);
add(a,T,l);
}
if(r!=inf)r-=l;
add(a,b,r);
}
int tS,tT;
int minflow(){
dicnic();
add(tT,tS,0,inf);
return dicnic();
}
int lp[4010],rp[4010],n,N;
int build(int l,int r,int f){
int siz=0,t,mid;
scanf("%d",&t);
if(l<r){
scanf("%d",&mid);
siz=build(l,mid,0)+build(mid+1,r,1);
}
if(!t&&siz)throw"OwO";
if(t){
add(tS,N,0,inf);
add(N,N+1,!siz,inf);
add(N+1,tT,0,inf);
if(f==1){
add(rp[l],N,0,inf);
if(r<n){
add(N+1,rp[r+1],0,inf);
add(N+1,lp[r+1],0,inf);
}
}
if(f==0){
add(rp[l],N,0,inf);
add(lp[l],N,0,inf);
if(r<n)add(N+1,lp[r+1],0,inf);
}
N+=2;
}
return siz+t;
}
int main(){
scanf("%d",&n);
try{
S=1;
T=2;
tS=3;
tT=4;
for(int i=1;i<=n;i++){
lp[i]=i+4;
rp[i]=i+n+4;
}
N=rp[n]+1;
build(1,n,-1);
printf("%d",minflow());
}catch(const char*s){
puts(s);
}
}