长郡邀请赛的题目...
首先行列是可以分开考虑的,任意两个排列都对应了一种方案,那么就一维一维考虑,首先可以用贪心求出一组可行解,因为每一维相当于是有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&#