• UOJ #217. 【UNR #1】奇怪的线段树


    Description

    给出一棵二叉树的结构,每次询问一个区间,将路径上的点染黑,求最小询问次数。

    Solution

    网络流。

    好厉害的题啊 =w=。

    首先可以发现的是,询问一个区间,一定是一段连续的左节点加上一段连续的右节点。

    如果是左节点,代表区间([l,r]),那么另一个询问的端点一定是([r+1,x])的左节点,也就是说不能出现左右两个节点,因为这样可以向上合并。

    如果是右节点,那么只需要满足另一个端点是(r+1)即可。

    这样可以跑最小流,首先拆一下点,如果不是最下面的节点,那么对于它其实没有限制,因为如果满足了它下面的节点,它一定有流量。

    如果是下面的节点,那么最小流量就是1

    题解里好像建了辅助节点,来优化建图。

    我并没有建辅助节点,而是将树上的左节点连接起来,因为满足条件的是一段左端点相同的点,所以直连左节点即可。

    建树的同时,记录一下左端点为(x)的最靠上的点。

    对于右节点就直接连最上面的点即可,左节点就连最上面的点的左节点即可。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define cg (2*n-1)
    #define lc(o) ch[o][0]
    #define rc(o) ch[o][1]
    
    const int N = 4080*4;
    const int oo = 0x3f3f3f3f;
    
    inline int in(int x=0,char ch=getchar()) { while(ch>'9' || ch<'0') ch=getchar();
    	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x; }
    
    int n,rt,flag;
    int ch[N][2],b[N],f[N],bb[N],L[N],R[N],tp[N];
    
    struct Edge { int fr,to,fl; };
    struct Network {
    	vector<Edge> edge;
    	vector<int> g[N];
    	int S,T,s,t,cnt,k,d[N],cur[N],du[N],p[N];
    	
    	void AddEdge(int fr,int to,int fl) {
    		edge.push_back((Edge) { fr,to,fl });
    		edge.push_back((Edge) { to,fr, 0 });
    		g[fr].push_back(edge.size()-2);
    		g[to].push_back(edge.size()-1);
    	}
    	void AddEdge(int fr,int to,int l,int r) {
    		AddEdge(fr,to,r-l),du[fr]-=l,du[to]+=l;
    	}
    	int BFS(int s,int t) {
    		memset(d,0xff,sizeof(d));
    		queue<int> q;
    		d[s]=1,q.push(s);
    		for(int x;!q.empty();) {
    			x=q.front(),q.pop();
    			for(int i=0;i<(int)g[x].size();i++) {
    				Edge &e=edge[g[x][i]];
    				if(e.fl && d[e.to]==-1) d[e.to]=d[x]+1,q.push(e.to);
    			}
    		}return d[t]!=-1;
    	}
    	int Dinic(int s,int t) {
    		int flow=0;
    		for(int x;BFS(s,t);) {
    //			puts("qqqwq");
    			for(memset(cur,0,sizeof(cur)),x=s,k=0;;) {
    				if(x==t) {
    					int mine=0,minf=oo;
    					for(int i=0;i<k;i++)
    						if(edge[p[i]].fl<minf) minf=edge[p[i]].fl,mine=i;
    					for(int i=0;i<k;i++) 
    						edge[p[i]].fl-=minf,edge[p[i]^1].fl+=minf;
    					flow+=minf,k=mine,x=edge[p[mine]].fr;
    				}
    				for(int &i=cur[x];i<(int)g[x].size();i++) {
    					Edge &e=edge[g[x][i]];
    					if(d[x]+1==d[e.to] && e.fl) break;
    				}
    				if(cur[x]<(int)g[x].size()) {
    					p[k++]=g[x][cur[x]],
    					x=edge[g[x][cur[x]]].to;
    				} else {
    					if(!k) break;
    					d[x]=-1,x=edge[p[--k]].fr;
    				}
    			}
    //			cout<<flow<<endl;
    		}return flow;
    	}
    	void Build(int &x,int l,int r) {
    		x=++cnt;
    		if(!tp[l]) tp[l]=x;
    		L[x]=l,R[x]=r;
    		if(l==r) {
    			bb[x]=b[x]=in();
    			if(b[x]) AddEdge(x,x+cg,1,oo);
    		} else {
    			b[x]=in();
    			int m=in();
    			Build(lc(x),l,m),Build(rc(x),m+1,r);
    			AddEdge(x+cg,lc(x),0,oo);
    			if(bb[lc(x)]||bb[rc(x)]) {
    				if(!b[x]) flag=1;
    				else AddEdge(x,x+cg,0,oo);
    			} else {
    				if(b[x]) AddEdge(x,x+cg,1,oo);
    			}
    			bb[x]=b[x]||bb[lc(x)]||bb[rc(x)];
    			f[lc(x)]=f[rc(x)]=x;
    		}
    	}
    	void main() {
    		flag=0;
    		n=in();
    		S=++cnt,T=++cnt,s=++cnt,t=++cnt;
    		Build(rt,1,n);
    //		puts("qwq");
    		if(flag) { cout<<"OwO"<<endl;return; }
    		for(int i=1;i<=cg;i++) {
    			AddEdge(s,cnt-cg+i,0,oo);
    			AddEdge(cnt+i,t,0,oo);
    		}
    		for(int i=cnt-cg+2;i<=cnt;i++) {
    			int d=rc(f[i])==i;
    //			cout<<d<<endl;
    			if(!d) {
    				if(tp[R[i]+1] && lc(tp[R[i]+1])) 
    					AddEdge(i+cg,lc(tp[R[i]+1]),0,oo);
    			} else {
    				if(tp[R[i]+1]) 
    					AddEdge(i+cg,tp[R[i]+1],0,oo);
    			}
    		}
    		cnt+=cg;
    		for(int i=3;i<=cnt;i++) {
    			if(du[i]<0) AddEdge(i,T,-du[i]);
    			else if(du[i]>0) AddEdge(S,i,du[i]);
    		}
    //		for(int i=1;i<=cnt;i++) cout<<du[i]<<" ";cout<<endl;
    //		for(int i=0;i<(int)edge.size();i+=2) {
    //			cout<<edge[i].fr<<"-->"<<edge[i].to<<" "<<edge[i].fl<<endl;
    //		}
    		
    		Dinic(S,T);
    		AddEdge(t,s,oo);
    		cout<<Dinic(S,T)<<endl;
    	}
    }py;
    
    int main() {
    	py.main();
    	return 0;
    }
    

      

  • 相关阅读:
    H5实现查看图片和删除图片的效果
    HTTP 状态码(HTTP Status Code)
    HashMap详解(基于JDK 1.8)
    FutureTask详解
    ForkJoin框架详解
    final详解
    磁盘管理之inode与block
    如何在CentOS上安装一个2048小游戏
    Linux帮助手册(man)
    Linux入门-基础命令
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/6598623.html
Copyright © 2020-2023  润新知