【二分图匹配判定+线段树建边】pku1057

首先行列是可以分开考虑的,相两个排列
摘要由CSDN通过智能技术生成

长郡邀请赛的题目...

首先行列是可以分开考虑的,任意两个排列都对应了一种方案,那么就一维一维考虑,首先可以用贪心求出一组可行解,因为每一维相当于是有n个区间,然后给每个区间找一个代表元,求出可行解之后再用二分图来考虑,相当于是询问每条边是否一定在最大匹配中,然后因为某个方向的边数特别多不能暴力连边但是可以发现这些边都属于某个区间,因此可以用线段树来优化连边,线段树每层会连n条边到实际的点上,因此也就nlogn条边就可以对应上。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
const int oo=1073741819;
using namespace std;
int l[1000000],r[1000000],p1[1000000],p2[1000000];
int n,ss,N,m1,w_time,top;
int rel[1000000],low[1000000],st[1000000],u[1000000];
int tail[1000000],next[3000000],sora[3000000];
int L[1000000],R[1000000],v[1000000],b[1000000],bj[1000000];
int lx[1000000],rx[1000000],ly[1000000],ry[1000000];
struct sta{
	int pos;
	sta () {}
	sta (int x) {
		pos=x;
	}
	bool operator < (const sta &a) const {
		return r[pos]>r[a.pos];
	}
};
bool cmp(int i,int j)
{
	if (l[i]!=l[j]) return l[i]<l[j];
	return r[i]<r[j];
}
bool check(int L[],int R[],int p[])
{
	for (int i=1;i<=n;i++) u[i]=i;
	for (int i=1;i<=n;i++) l[i]=L[i],r[i]=R[i];
	sort(u+1,u+n+1,cmp);
	priority_queue <sta> Q;
	for (int i=1,j=1;i<=n;i++) {
		for (;(j<=n) && (l[u[j]]<=i);j++) Q.push(sta(u[j]));
		if (Q.empty()) return 0;
		sta tmp=Q.top();
		Q.pop();
		if (r[tmp.pos]<i) return 0;
		p[tmp.pos]=i;
		//cout<<tmp.pos<<endl;
	}
	return 1;
}
void link(int x,int y)
{
	++ss,next[tail[x]]=ss,tail[x]=ss,sora[ss]=y,next[ss]=0;
}
void link2(int x,int l,int r)
{
	if (l>r) return ;
	l+=m1-1,r&#
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值