传送门: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; }