传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2584
首先考虑第二问
显然只向一个方向移动一定有解 假设向上
显然构成了一个DAG图,拓扑排序即可
那么如何构造DAG图
由于线段是不相交的,所以在相邻两个横坐标之间的线段在y方向的相对位置不变!!!!
扫描线+set 维护前趋后继构建DAG图
考虑第一问
分别考虑水平和竖直方向
假设我们求出了竖直方向的拓扑序
把移除一个线段倒序改为添加一个线段
那么从上往下添加线段=>离散后的横坐标区间中的拓扑标号大于它
从下往上添加线段=>离散后的横坐标区间中的拓扑标号小于它
两个方向分别离散化+线段树,取其最小值即可
P.S.找来kAc的标程想对拍,然后越改越像越改越像……
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<queue>
#include<cstring>
#define fst first
#define sec second
using namespace std;
typedef pair<int,int> par;
const int maxn=1e5+5;
const double eps=1e-6;
int dcmp(double x){return (x>eps)-(x<-eps);}
struct point{
int x,y;
bool operator==(point o)const{return x==o.x&&y==o.y;}
bool operator<(const point &o)const{return x==o.x?y<o.y:x<o.x;}
};
int nowx;
struct line{
point a,b;int id;
double get(int x)const{return a.y+(double)(b.y-a.y)/(double)(b.x-a.x)*double(x-a.x);}
bool operator<(const line &o)const{return get(nowx)-o.get(nowx)<-eps;}
}lin[maxn];
set<line>S;
int n,in[maxn],anss[maxn],size;
par Q[maxn];
int X[maxn<<1];
int uniqX(int x){return lower_bound(X+1,X+1+X[0],x)-X;}
vector<int>G[maxn];
void add(int u,int v){
G[u].push_back(v);
}
void topsort(){
queue<int>q;
for(int i=1;i<=n;i++)if(!in[i]){q.push(i);anss[++anss[0]]=i;}
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0,v;i<G[u].size();i++)
if(!--in[v=G[u][i]])q.push(v),anss[++anss[0]]=v;
}
}
const int inf=1e9+10;
struct Tsgt{
int mn[maxn<<3],mx[maxn<<3],_mn[maxn<<3],_mx[maxn<<3];
void clear(){
memset(mn, 0x3f, sizeof(mn));memset(mx, 0xe0, sizeof(mx));
memset(_mn, 0x3f, sizeof(_mn));memset(_mx, 0xe0, sizeof(_mx));
}
void minadd(int i, int d){
mn[i] = min(mn[i], d);
_mn[i] = min(_mn[i], d);
}
void maxadd(int i, int d){
mx[i] = max(mx[i], d);
_mx[i] = max(_mx[i], d);
}
void update(int i){
mx[i] = max(mx[i * 2], mx[i * 2 + 1]);
mn[i] = min(mn[i * 2], mn[i * 2 + 1]);
}
void pd(int i){
if (_mn[i] != 0x3f3f3f3f) { minadd(i * 2, _mn[i]); minadd(i * 2 + 1, _mn[i]); }
if (_mx[i] != 0xe0e0e0e0) { maxadd(i * 2, _mx[i]); maxadd(i * 2 + 1, _mx[i]); }
_mn[i] = 0x3f3f3f3f; _mx[i] = 0xe0e0e0e0;
}
void Change(int i, int l, int r, int l0, int r0, int d){
if (l0 <= l && r0 >= r) { minadd(i, d); maxadd(i, d); return; }
int m = l + r >> 1;
pd(i);
if (l0 < m) Change(i * 2, l, m, l0, r0, d);
if (r0 > m) Change(i * 2 + 1, m, r, l0, r0, d);
update(i);
}
int Qmin(int i, int l, int r, int l0, int r0){
if (l0 <= l && r0 >= r) return mn[i];
int m = l + r >> 1;
pd(i);
int ans = 0x3f3f3f3f;
if (l0 < m) ans = min(ans, Qmin(i * 2, l, m, l0, r0));
if (r0 > m) ans = min(ans, Qmin(i * 2 + 1, m, r, l0, r0));
update(i);
return ans;
}
int Qmax(int i, int l, int r, int l0, int r0){
if (l0 <= l && r0 >= r) return mx[i];
int m = l + r >> 1;
pd(i);
int ans = 0xe0e0e0e0;
if (l0 < m) ans = max(ans, Qmax(i * 2, l, m, l0, r0));
if (r0 > m) ans = max(ans, Qmax(i * 2 + 1, m, r, l0, r0));
update(i);
return ans;
}
}T;
int getint(){int x;scanf("%d",&x);return x;}
struct scanline{
int op,id,x;
bool operator<(const scanline &o)const{return x!=o.x?x<o.x:op<o.op;}
}scan[maxn<<2];
int val[maxn];
int solve(int d){
S.clear();size=0;T.clear();
for(int i=1;i<=n;i++){
G[i].clear();
scan[++size]=(scanline){1,i,lin[i].a.x};
scan[++size]=(scanline){2,i,lin[i].a.x};
scan[++size]=(scanline){2,i,lin[i].b.x};
scan[++size]=(scanline){3,i,lin[i].b.x};
}sort(scan+1,scan+1+size);X[0]=0;
for(int i=1;i<=n;i++)X[++X[0]]=lin[i].a.x,X[++X[0]]=lin[i].b.x;
sort(X+1,X+1+X[0]);X[0]=unique(X+1,X+1+X[0])-X-1;
for(int i=1;i<=size;i++){
set<line>::iterator it,iter;
nowx=scan[i].x;
if(scan[i].op==1)S.insert(lin[scan[i].id]);
else if(scan[i].op==2){
it=S.find(lin[scan[i].id]);iter=it;iter++;
if(it!=S.begin()){it--;add(scan[i].id,it->id);in[it->id]++;}
if(iter!=S.end()){add(iter->id,scan[i].id);in[scan[i].id]++;}
}else S.erase(lin[scan[i].id]);
}anss[0]=0;topsort();
for(int i=1;i<=n;i++)val[anss[i]]=i;
int ans=n;
for(int i=n;i>=1;i--){
int id=Q[i].fst,di=Q[i].sec;
if((di&1)==d){
if(di>>1)
{if(T.Qmax(1,1,X[0],uniqX(lin[id].a.x),uniqX(lin[id].b.x))>val[id])ans=i;}
else {if(T.Qmin(1,1,X[0],uniqX(lin[id].a.x),uniqX(lin[id].b.x))<val[id])ans=i;}
}T.Change(1,1,X[0],uniqX(lin[id].a.x),uniqX(lin[id].b.x),val[id]);
}return ans;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
point a,b;a.x=getint();a.y=getint();
b.x=getint();b.y=getint();
if(b<a)swap(a,b);
lin[i]=(line){a,b,i};
}for(int i=1;i<=n;i++)Q[i].fst=getint(),Q[i].sec=getint();
int ans=solve(1);
for (int i=1;i<=n;i++){
swap(lin[i].a.x,lin[i].a.y);
swap(lin[i].b.x,lin[i].b.y);
lin[i].a.y*=-1;lin[i].b.y*=-1;
if(lin[i].b<lin[i].a)swap(lin[i].a,lin[i].b);
}ans=min(ans,solve(0));
cout<<ans<<endl;
for(int i=1;i<=n;i++)printf("%d 0\n",anss[i]);
return 0;
}