zoukankan      html  css  js  c++  java
  • uoj#217. 【UNR #1】奇怪的线段树(上下界最小流)

    题目描述

    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;
    }
    
  • 相关阅读:
    bat文件转换为exe文件
    桌面快捷方式增(删)
    客户推广微信小程序的几种方法如下
    小程序开发客户对接流程
    Java MySQL 连接
    前端开发构建工具
    [转]chrome 的devtools 中setting 开启workspace , 也有点用处。不是很大
    回归基础的东西,不能只是“感觉会了”
    angular 的ui.router 定义不同的state 对应相同的url
    学习javascript 非常好的博客
  • 原文地址:https://www.cnblogs.com/gmh77/p/13417631.html
Copyright © 2011-2022 走看看