1 条题解

  • 1
    @ 2022-8-24 9:05:05
    #include<bits/stdc++.h>
    using namespace std;
    int read() {
    	int q=0,w=1;char ch=' ';
    	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    	if(ch=='-') w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();
    	return q*w;
    }
    #define RI register int
    const int N=50010,inf=0x3f3f3f;
    int n,jsx,jsy,js1,js2;
    struct node{int x,y,b1,b2,id;}p[N];
    int bx[N],by[N],bb1[N],bb2[N];
    
    int up[N],lup[N],rup[N],f[N],Tx[N],Tb1[N],Tb2[N],bj[N],tx[N],ty[N],gup[N],bup[N];
    //gup:往上走最多走几棵树,bup:往上走走最多的树,下一步走到哪颗树,bj:记录方案,T开头的都是桶
    bool cmpy(node a,node b) {return a.y>b.y;}
    bool cmpx(node a,node b) {return a.x<b.x;}
    vector<int> iny[N];
    void prework() {//预处理每个点左上,右上,正上是那些点
    	sort(bx+1,bx+1+n),sort(by+1,by+1+n);
    	sort(bb1+1,bb1+1+n),sort(bb2+1,bb2+1+n);
    	jsx=1;for(RI i=2;i<=n;++i) if(bx[i]!=bx[jsx]) bx[++jsx]=bx[i];
    	jsy=1;for(RI i=2;i<=n;++i) if(by[i]!=by[jsy]) by[++jsy]=by[i];
    	js1=1;for(RI i=2;i<=n;++i) if(bb1[i]!=bb1[js1]) bb1[++js1]=bb1[i];
    	js2=1;for(RI i=2;i<=n;++i) if(bb2[i]!=bb2[js2]) bb2[++js2]=bb2[i];
    	for(RI i=1;i<=n;++i) {
    		p[i].x=lower_bound(bx+1,bx+1+jsx,p[i].x)-bx,tx[i]=p[i].x;
    		p[i].y=lower_bound(by+1,by+1+jsy,p[i].y)-by,ty[i]=p[i].y;
    		p[i].b1=lower_bound(bb1+1,bb1+1+js1,p[i].b1)-bb1;
    		p[i].b2=lower_bound(bb2+1,bb2+1+js2,p[i].b2)-bb2;
    	}
    	sort(p+1,p+1+n,cmpy);
    	for(RI i=1;i<=n;++i) {
    		int k=p[i].id;
    		up[k]=Tx[p[i].x],lup[k]=Tb1[p[i].b1],rup[k]=Tb2[p[i].b2];
    		Tx[p[i].x]=Tb1[p[i].b1]=Tb2[p[i].b2]=k;
    	}
    	sort(p+1,p+1+n,cmpx);
    	for(RI i=1;i<=n;++i) iny[p[i].y].push_back(p[i].id);
    }
    void print(int num) {//输出方案
    	int y=ty[num],sz=iny[y].size(),nxt=bj[num];
    	if(num!=n) printf("%d ",num);
    	if(tx[nxt]<tx[num]) {
    		for(RI i=0;i<sz;++i)
    			if(tx[iny[y][i]]>tx[num]) printf("%d ",iny[y][i]);
    		for(RI i=sz-1;i>=0;--i)
    			if(tx[iny[y][i]]<tx[num]&&tx[iny[y][i]]>=tx[nxt]) printf("%d ",iny[y][i]);
    	}
    	else if(tx[nxt]>tx[num]) {
    		for(RI i=sz-1;i>=0;--i)
    			if(tx[iny[y][i]]<tx[num]) printf("%d ",iny[y][i]);
    		for(RI i=0;i<sz;++i)
    			if(tx[iny[y][i]]>tx[num]&&tx[iny[y][i]]<=tx[nxt]) printf("%d ",iny[y][i]);
    	}
    	if(bup[nxt]) print(bup[nxt]);
    }
    void work1() {//DP主体
    	prework();
    	for(RI y=jsy;y>=1;--y) {
    		int kmx=0,kbj=0,sz=iny[y].size();
    		for(RI i=0;i<sz;++i) {
    			int k=iny[y][i];
    			if(up[k]&&f[up[k]]>gup[k]) gup[k]=f[up[k]],bup[k]=up[k];
    			if(lup[k]&&f[lup[k]]>gup[k]) gup[k]=f[lup[k]],bup[k]=lup[k];
    			if(rup[k]&&f[rup[k]]>gup[k]) gup[k]=f[rup[k]],bup[k]=rup[k];
    			f[k]=kmx,bj[k]=kbj;
    			if(sz-i+gup[k]>kmx) kmx=sz-i+gup[k],kbj=k;
    		}
    		kmx=kbj=0;
    		for(RI i=sz-1;i>=0;--i) {
    			int k=iny[y][i];
    			if(kmx>f[k]) f[k]=kmx,bj[k]=kbj;
    			if(gup[k]+1>f[k]) f[k]=gup[k]+1,bj[k]=k;
    			if(i+1+gup[k]>kmx) kmx=i+1+gup[k],kbj=k;
    		}
    	}
    	printf("%d\n",f[n]-1),print(n),puts("");
    }
    
    int tot=1,S,T,ss,tt,ans;
    int ok[N],du[N],h[N],ne[N*10],to[N*10],flow[N*10],lev[N],q[N];
    void adde(int x,int y,int z) {
    	to[++tot]=y,ne[tot]=h[x],h[x]=tot,flow[tot]=z;
    	to[++tot]=x,ne[tot]=h[y],h[y]=tot,flow[tot]=0;
    }
    void add(int x,int y) {
    	for(RI i=h[x];i;i=ne[i]) if(to[i]==y) return;//注意不要重复(由于数据特殊性不会很慢)
    	ok[y]=1,++du[y],--du[x],adde(x,y,inf);
    }
    void calc(int y,int i) {//暴力查看符合条件的点
    	int sz=iny[y].size(),num=iny[y][i];
    	for(RI j=0;j<i;++j) {
    		int k=iny[y][j];
    		if(up[k]&&f[up[k]]+sz-j==f[num]) add(k,up[k]);
    		if(lup[k]&&f[lup[k]]+sz-j==f[num]) add(k,lup[k]);
    		if(rup[k]&&f[rup[k]]+sz-j==f[num]) add(k,rup[k]);
    	}
    	for(RI j=i+1;j<sz;++j) {
    		int k=iny[y][j];
    		if(up[k]&&f[up[k]]+j+1==f[num]) add(k,up[k]);
    		if(lup[k]&&f[lup[k]]+j+1==f[num]) add(k,lup[k]);
    		if(rup[k]&&f[rup[k]]+j+1==f[num]) add(k,rup[k]);
    	}
    	if(up[num]&&f[up[num]]+1==f[num]) add(num,up[num]);
    	if(lup[num]&&f[lup[num]]+1==f[num]) add(num,lup[num]);
    	if(rup[num]&&f[rup[num]]+1==f[num]) add(num,rup[num]);
    }
    void build() {//网络流建图
    	ok[n]=1;
    	for(RI y=1;y<=jsy;++y) {
    		int sz=iny[y].size();
    		for(RI i=0;i<sz;++i) if(ok[iny[y][i]]) calc(y,i);
    	}
    }
    int dfs(int x,int liu,int t) {//dinic的dfs
    	if(x==t) return liu;
    	int kl,sum=0;
    	for(RI i=h[x];i;i=ne[i])
    		if(flow[i]>0&&lev[to[i]]==lev[x]+1) {
    			kl=dfs(to[i],min(flow[i],liu-sum),t);
    			sum+=kl,flow[i]-=kl,flow[i^1]+=kl;
    			if(sum==liu) return sum;
    		}
    	if(!sum) lev[x]=-1;
    	return sum;
    }
    int bfs(int s,int t) {//dinic的bfs
    	for(RI i=1;i<=n+4;++i) lev[i]=0;
    	int he=1,ta=1; lev[s]=1,q[1]=s;
    	while(he<=ta) {
    		int x=q[he];++he;
    		if(x==t) return 1;
    		for(RI i=h[x];i;i=ne[i])
    			if(flow[i]>0&&!lev[to[i]])
    				lev[to[i]]=lev[x]+1,q[++ta]=to[i];
    	}
    	return 0;
    }
    void work2() {
    	build();
    	S=n+1,T=n+2,ss=n+3,tt=n+4;
    	for(RI i=1;i<=n;++i) {
    		if(du[i]>0) adde(ss,i,du[i]),ans+=du[i];
    		else adde(i,tt,-du[i]);
    	}
    	while(bfs(ss,tt)) ans-=dfs(ss,inf,tt);
    	printf("%d\n",ans);
    }
    
    int main()
    {
    	n=read();
    	for(RI i=1;i<=n;++i) {
    		bx[i]=p[i].x=read(),by[i]=p[i].y=read();
    		bb1[i]=p[i].b1=p[i].y-p[i].x,bb2[i]=p[i].b2=p[i].x+p[i].y;
    		p[i].id=i;
    	}
    	++n,p[n].id=n;
    	work1(),work2();
        return 0;
    }
    
    • 1

    信息

    ID
    1255
    时间
    1000ms
    内存
    500MiB
    难度
    7
    标签
    递交数
    3
    已通过
    3
    上传者