Jzoj3163 排列

给你M个对1到N的排列的特征,特征有两种:

1 x y v:排列的第x个数到第y个数之间的最大值为v

2 x y v:排列的第x个数到第y个数之间的最小值为v

要求你还原出这个排列(N<=200,M<=40000)

刷水题有利于身心健康

但你还不是不会做?额这

想必许多人看完题目就知道怎么做了吧,才200直接二分图匹配就搞定了啊,O(NM)建图没问题

(另外,2014年那时候还没有匈牙利算法吗?为什么好多人直接写暴力网络流还跑的飞快)

#pragma GCC opitmize("O3")
#pragma G++ opitmize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char s[210][210];
int n,m,f[210],v[210];
inline bool match(int x){
	for(int j=1;j<=n;++j)
		if(s[x][j]&&!v[j]){
			v[j]=1;
			if(!f[j]||match(f[j])){
				f[j]=x; return 1;
			}
		}
	return 0;
}
int main(){
	scanf("%d%d",&n,&m);
	memset(s,1,sizeof s);
	for(int o,l,r,v;m--;){
		scanf("%d%d%d%d",&o,&l,&r,&v);
		if(o==1) 
			for(int i=l;i<=r;++i) memset(s[i]+v+1,0,n-v);
		else for(int i=l;i<=r;++i) memset(s[i],0,v);
		for(int i=1;i<l;++i) s[i][v]=0;rt
		for(int i=n;i>r;--i) s[i][v]=0;
	}
	for(int i=1;i<=n;++i){
		memset(v,0,sizeof v);
		if(!match(i)) return 0&puts("-1"); 
	}
	for(int i=1;i<=n;++i) v[f[i]]=i;
	for(int i=1;i<=n;++i) printf("%d ",v[i]);
}

posted @ 2018-01-02 20:48  扩展的灰(Extended_Ash)  阅读(160)  评论(0编辑  收藏  举报