记录编号 245310 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2015]小园丁与老司机 最终得分 100
用户昵称 Gravatar神利·代目 是否通过 通过
代码语言 C++ 运行时间 3.966 s
提交时间 2016-04-02 21:45:14 内存使用 134.39 MiB
显示代码纯文本
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define inf 0x3fffffff
int n,L[500100],R[500100];
inline int MIN(int A,int B){return A<B?A:B;}
inline int MAX(int A,int B){return A>B?A:B;}
struct node{int x,y,he,cha,id,orid;}a[500100];
inline bool comp_x(node a,node b){return a.x==b.x?a.y<b.y:a.x<b.x;}
inline bool comp_y(node a,node b){return a.y==b.y?a.x<b.x:a.y<b.y;}
inline bool comp_he(node a,node b){return a.he==b.he?a.y<b.y:a.he<b.he;}
inline bool comp_cha(node a,node b){return a.cha==b.cha?a.y<b.y:a.cha<b.cha;}
int shu,first[500100],firs[500100];
struct edge{int v,w,nx;}o[2100000],e[2100000],O[4100000];
inline void add(int u,int v){
	o[++shu].v=v,o[shu].nx=first[u],first[u]=shu;
	e[shu].v=u,e[shu].nx=firs[v],firs[v]=shu;
}
int SHU,FIRST[500100];
inline void ADD(int u,int v,int w){
	O[++SHU].v=v,O[SHU].w=w,O[SHU].nx=FIRST[u],FIRST[u]=SHU;
}
int ans,f[500100],g[500100],f2[500100],g2[500100],nx[500100][2];
void init(){
	scanf("%d",&n),++n;
	for(int i=1;i<n;++i) scanf("%d%d",&a[i].x,&a[i].y),a[i].he=a[i].x+a[i].y,a[i].cha=a[i].x-a[i].y,a[i].orid=i;
	std::sort(a,a+n,comp_y);
	for(int i=0;i<n;++i,f[i]=-inf) a[i].id=i;
	for(int i=1,last=0;i<n;++i){
		if(a[i].y!=a[last].y) L[++L[0]]=last,R[L[0]]=i-1,last=i;
		if(i==n-1) L[++L[0]]=last,R[L[0]]=i;
	}
	std::sort(a,a+n,comp_x);
	for(int i=1;i<n;++i)
	    if(a[i].x==a[i-1].x)
	        add(a[i-1].id,a[i].id);
	std::sort(a,a+n,comp_he);
	for(int i=1;i<n;++i)
	    if(a[i].he==a[i-1].he)
	        add(a[i-1].id,a[i].id);
	std::sort(a,a+n,comp_cha);
	for(int i=1;i<n;++i)
	    if(a[i].cha==a[i-1].cha)
	        add(a[i-1].id,a[i].id);
}
void dp(){
	std::sort(a,a+n,comp_y);
	for(int i=1,mx;i<=L[0];++i){
		for(int j=L[i],mx=-inf;j<=R[i];++j){
			g[j]=MAX(mx+j-L[i]+1,f[j]+1);
			for(int k=first[j];k;k=o[k].nx)
				if(f[o[k].v]<g[j])
				    f[o[k].v]=g[j];
			mx=MAX(mx,f[j]);
		}
		for(int j=R[i],mx=-inf;j>=L[i];--j){
			g[j]=MAX(g[j],MAX(mx+R[i]-j+1,f[j]+1));
			for(int k=first[j];k;k=o[k].nx)
				if(f[o[k].v]<g[j])
				    f[o[k].v]=g[j];
			mx=MAX(mx,f[j]);
		}
	}
	for(int i=L[0];i;--i){
		for(int j=R[i],mx=-inf,now;j>=L[i];--j){
			if(g2[j]<=f2[j]+1) g2[j]=f2[j]+1,nx[j][1]=j;
			if(g2[j]<=mx) g2[j]=mx,nx[j][1]=now;
			for(int k=firs[j];k;k=e[k].nx)
				if(f2[e[k].v]<g2[j])
				    f2[e[k].v]=g2[j],nx[e[k].v][0]=j;
			if(mx<f2[j]+j-L[i]+1) mx=f2[j]+j-L[i]+1,now=j;
		}
		for(int j=L[i],mx=-inf,now;j<=R[i];++j){
			if(g2[j]<=f2[j]+1) g2[j]=f2[j]+1,nx[j][1]=j;
			if(g2[j]<=mx) g2[j]=mx,nx[j][1]=now;
			for(int k=firs[j];k;k=e[k].nx)
				if(f2[e[k].v]<=g2[j])
				    f2[e[k].v]=g2[j],nx[e[k].v][0]=j;
			if(mx<f2[j]+R[i]-j+1) mx=f2[j]+R[i]-j+1,now=j;
		}
	}
	ans=g2[0];
	printf("%d\n",ans-1);
}
void path(){
	int now=0,tmp;
	while(nx[now][0]||nx[nx[now][0]][1]){
		now=nx[now][0];
		if(now==nx[now][1]) printf("%d ",a[now].orid);
		else{
			if(a[nx[now][1]].x<a[now].x){
				tmp=now;
				while(a[tmp].y==a[now].y) printf("%d ",a[tmp].orid),++tmp;
				tmp=now-1;
				while(tmp!=nx[now][1]) printf("%d ",a[tmp].orid),--tmp;
			}else{
				tmp=now;
				while(a[tmp].y==a[now].y) printf("%d ",a[tmp].orid),--tmp;
				tmp=now+1;
				while(tmp!=nx[now][1]) printf("%d ",a[tmp].orid),++tmp;
			}
			printf("%d ",a[now=nx[now][1]].orid);
		}
	}
}
bool flag[500100][2];
int S,T,ru[500100];
void build(){
	SHU=1;
	S=n+2,T=n+3;
	int s=n,t=n+1;
	for(int i=1;i<=shu;++i)
	    if(g[e[i].v]+g2[o[i].v]==ans){
			ADD(e[i].v,o[i].v,inf),ADD(o[i].v,e[i].v,0),++ru[o[i].v],--ru[e[i].v];
			if(!flag[e[i].v][0]) ADD(s,e[i].v,inf),ADD(e[i].v,s,0),flag[e[i].v][0]=1;
			if(!flag[o[i].v][1]) ADD(o[i].v,t,inf),ADD(t,o[i].v,0),flag[o[i].v][1]=1;
	    }
	for(int i=0;i<=t;++i)
	    if(ru[i]>0) ADD(S,i,ru[i]),ADD(i,S,0);
	    else if(ru[i]<0) ADD(i,T,-ru[i]),ADD(T,i,0);
}
int l,r,d[500100],q[500100];
inline bool BFS(int s,int t){
	memset(d,0,sizeof(d));
	q[l=r=0]=s,d[s]=1;
	while(l<=r){
		s=q[l++];
		for(int i=FIRST[s];i;i=O[i].nx)
		    if(O[i].w&&!d[O[i].v]){
				d[O[i].v]=d[s]+1;
				if(O[i].v==t) return 1;
				q[++r]=O[i].v;
		    }
	}
	return 0;
}
inline int DFS(int x,int t,int flow){
	if(x==t) return flow;
	int tmp=flow,k;
	for(int i=FIRST[x];i&&tmp;i=O[i].nx)
	    if(O[i].w&&d[O[i].v]==d[x]+1){
			k=DFS(O[i].v,t,MIN(tmp,O[i].w));
			if(!k) d[O[i].v]=0;
			tmp-=k,O[i].w-=k,O[i^1].w+=k;
	    }
	return flow-tmp;
}
void DINIC(){
	int maxflow=0,flow;
	while(BFS(S,T)) while(flow=DFS(S,T,inf)) maxflow+=flow;
	ans=maxflow;
}
int main(){
	freopen("farm.in","r",stdin);
	freopen("farm.out","w",stdout);
	init();
	dp();
	path();
	build();
	DINIC();
	ADD(n+1,n,inf),ADD(n,n+1,0);
	DINIC();
	printf("\n%d",ans);
}