题目描述
n<=4000
题解
线段树性质:一次区间查找从左往右对应右子树->右子树->...->左子树->左子树
把[l,r]向r+1连边,r+1向[r+1,l']连边,跑上下界最小流即可
上下界最小流=上下界可行流-残量网络T->S最大流,可行流=T->S的inf边跑过的流量
染色树的叶子节点要经过至少一次,非叶子可以经过任意次,没有染色的点不能经过
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define inf 114514
#define ll long long
//#define file
using namespace std;
int a[2000001][3],tr[8001][2],d[8001],ls[30001],cur[30001],f[30001],g[30001];
int L[8001],R[8001],Tr[8001],A[8001],B[8001],n,i,j,k,l,t,tot,t1,t2,len,ans,S,T;
bool bz1[8001],bz2[8001];
void NEW(int x,int y,int z) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;a[len][2]=z;}
void New(int x,int y,int z) {NEW(x,y,z),NEW(y,x,0);}
void pd(int Fa,int t)
{
if (Tr[t] && (!tr[t][0] || !Tr[tr[t][0]] && !Tr[tr[t][1]]))
{
if (tr[Fa][0]==t) bz1[t]=1;
else bz2[t]=1;
}
if (t>1) {if (tr[Fa][0]==t) A[++t1]=t; else B[++t2]=t;}
if (!tr[t][0]) return;
if (!Tr[t] && Tr[tr[t][0]]) {printf("OwO
");exit(0);}
if (!Tr[t] && Tr[tr[t][1]]) {printf("OwO
");exit(0);}
pd(t,tr[t][0]),pd(t,tr[t][1]);
}
int dfs(int t,int flow)
{
int i,use=0,w;
if (t==T) return flow;
for (i=cur[t]; i; i=a[i][1])
if (a[i][2] && f[t]==f[a[i][0]]+1)
{
cur[t]=i;
w=dfs(a[i][0],min(flow-use,a[i][2]));
a[i][2]-=w,a[i^1][2]+=w;
use+=w;
if (flow==use) return use;
}
cur[t]=ls[t];
--g[f[t]];
if (!g[f[t]]) {f[S]=T+1;return use;}
++f[t],++g[f[t]];
return use;
}
int main()
{
#ifdef file
freopen("uoj217.in","r",stdin);
#endif
scanf("%d",&n);
t=tot=1;L[1]=1;R[1]=n;d[t]=1;
fo(i,1,n*2-1)
{
scanf("%d",&j);Tr[d[t]]=j;
if (L[d[t]]!=R[d[t]])
{
scanf("%d",&k);
tr[d[t]][0]=++tot;L[tot]=L[d[t]];R[tot]=k;
tr[d[t]][1]=++tot;L[tot]=k+1;R[tot]=R[d[t]];
l=d[t],d[++t]=tr[l][0];
}
else
{
--t;
while (t && tr[d[t]][1]==d[t+1]) --t;
if (t) l=d[t],d[++t]=tr[l][1];
}
}
pd(0,1);
if (!Tr[1]) {printf("0
");return 0;}
if (Tr[1] && !Tr[tr[1][0]] && !Tr[tr[1][1]]) {printf("1
");return 0;}
S=(n+tot)*2+1;T=S+1;
len=1;
fo(i,1,n) New(i,i+n,inf);
fo(i,1,t2)
if (Tr[B[i]])
{
New(T,B[i]+n*2,inf);
New(B[i]+n*2,B[i]+n*2+tot,inf);
if (bz2[B[i]]) New(T+1,B[i]+n*2+tot,1),New(B[i]+n*2,T+2,1);
New(B[i]+n*2+tot,S,inf);
New(L[B[i]],B[i]+n*2,inf);
if (R[B[i]]<n)
New(B[i]+n*2+tot,R[B[i]]+1,inf);
}
fo(i,1,t1)
if (Tr[A[i]])
{
New(T,A[i]+n*2,inf);
New(A[i]+n*2,A[i]+n*2+tot,inf);
if (bz1[A[i]]) New(T+1,A[i]+n*2+tot,1),New(A[i]+n*2,T+2,1);
New(A[i]+n*2+tot,S,inf);
New(L[A[i]]+n,A[i]+n*2,inf);
if (R[A[i]]<n)
New(A[i]+n*2+tot,R[A[i]]+n+1,inf);
}
New(S,T,inf);
S+=2,T+=2;g[0]=T;
while (f[S]<=T) dfs(S,inf);ans=a[len][2];
memset(f,0,sizeof(f)),memset(g,0,sizeof(g)),memset(cur,0,sizeof(cur));
S-=2,T-=2;g[0]=T;a[len][2]=a[len^1][2]=0;
while (f[S]<=T) ans-=dfs(S,inf);
printf("%d
",ans);
fclose(stdin);
fclose(stdout);
return 0;
}