%%% zky :http://blog.csdn.net/iamzky/article/details/42166795
“P.S.找来kAc的标程想对拍,然后越改越像越改越像……”——zky
自己YY出来一个区间取 max min 的线段树
找来zky的程序 然后越改越像
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#define V G[p].v
#define eps 1e-6
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x)
{
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int maxn=100005;
struct SEGTREE{
int Mx[maxn*8],Mn[maxn*8],HMx[maxn*8],HMn[maxn*8];
int M,TH;
inline void Pushup(int p){
Mx[p]=max(Mx[p<<1],Mx[p<<1|1]);
Mn[p]=min(Mn[p<<1],Mn[p<<1|1]);
}
inline void Build(int n){
for (M=1,TH=0;M<n+2;M<<=1,TH++);
memset(Mx,0,sizeof(Mx));
memset(Mn,0x7f,sizeof(Mn));
memset(HMx,0,sizeof(HMx));
memset(HMn,0x7f,sizeof(HMn));
}
inline void Pushdown(int rt){
int p;
for (int i=TH;i;i--)
{
if (HMx[p=rt>>i])
{
HMx[p<<1]=max(HMx[p<<1],HMx[p]);
HMx[p<<1|1]=max(HMx[p<<1|1],HMx[p]);
if (HMx[p]>Mx[p<<1])
Mx[p<<1]=HMx[p];
if (HMx[p]>Mx[p<<1|1])
Mx[p<<1|1]=HMx[p];
HMx[p]=0;
}
if (HMn[p]<0x7f7f7f7f)
{
HMn[p<<1]=min(HMn[p<<1],HMn[p]);
HMn[p<<1|1]=min(HMn[p<<1|1],HMn[p]);
if (HMn[p]<Mn[p<<1])
Mn[p<<1]=HMn[p];
if (HMn[p]<Mn[p<<1|1])
Mn[p<<1|1]=HMn[p];
HMn[p]=0x7f7f7f7f;
}
}
}
inline void Change(int s,int t,int r){
for (Pushdown(s+=M-1),Pushdown(t+=M+1);s^t^1;Pushup(s>>=1),Pushup(t>>=1))
{
if (~s&1)
{
HMn[s^1]=min(HMn[s^1],r);
HMx[s^1]=max(HMx[s^1],r);
if (r<Mn[s^1])
Mn[s^1]=r;
if (r>Mx[s^1])
Mx[s^1]=r;
}
if ( t&1)
{
HMn[t^1]=min(HMn[t^1],r);
HMx[t^1]=max(HMx[t^1],r);
if (r<Mn[t^1])
Mn[t^1]=r;
if (r>Mx[t^1])
Mx[t^1]=r;
}
}
while (s>>=1)
Pushup(s);
}
inline int Max(int s,int t){
int ret=0;
for (Pushdown(s+=M-1),Pushdown(t+=M+1);s^t^1;s>>=1,t>>=1)
{
if (~s&1) ret=max(ret,Mx[s^1]);
if ( t&1) ret=max(ret,Mx[t^1]);
}
return ret;
}
inline int Min(int s,int t){
int ret=1<<30;
for (Pushdown(s+=M-1),Pushdown(t+=M+1);s^t^1;s>>=1,t>>=1)
{
if (~s&1) ret=min(ret,Mn[s^1]);
if ( t&1) ret=min(ret,Mn[t^1]);
}
return ret;
}
}SEG;
struct edge{
int u,v;
int next;
};
edge G[1000005];
int head[maxn],inum;
inline void add(int u,int v,int p){
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
int n,Ans;
int lst[maxn],pnt,vst[maxn];
int rank[maxn];
inline void dfs(int u){
vst[u]=1;
for (int p=head[u];p;p=G[p].next)
if (!vst[V])
dfs(V);
lst[++pnt]=u;
}
inline void Topo()
{
cl(vst); pnt=0;
for (int i=1;i<=n;i++)
if (!vst[i])
dfs(i);
reverse(lst+1,lst+n+1);
}
inline int dcmp(double a,double b)
{
if (fabs(a-b)<eps) return 0;
if (a<b) return -1;
return 1;
}
struct Point{
int x,y;
Point(int x=0,int y=0):x(x),y(y) { }
inline bool operator == (const Point &B) const{
return x==B.x && y==B.y;
}
inline bool operator < (const Point &B) const{
return x==B.x?y<B.y:x<B.x;
}
};
int Curx;
struct Line{
Point a,b;
int id;
Line(Point a=Point(0,0),Point b=Point(0,0),int id=0):a(a),b(b),id(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 &B)const{
return dcmp(get(Curx),B.get(Curx))<0;
}
}L[maxn];
set<Line> Set;
typedef set<Line>::iterator ITER;
struct event{
int x,id,f;
event(int x=0,int id=0,int f=0):x(x),id(id),f(f) { }
bool operator < (const event &B) const{
return x==B.x?f<B.f:x<B.x;
}
}eve[4*maxn];
int tot;
pair<int,int> Q[maxn];
int uniq[2*maxn];
int icnt;
inline int Bin(int x){
return lower_bound(uniq+1,uniq+icnt+1,x)-uniq;
}
inline int Solve(int d)
{
tot=0;
for (int i=1;i<=n;i++)
{
eve[++tot]=event(L[i].a.x,i,1);
eve[++tot]=event(L[i].a.x,i,2);
eve[++tot]=event(L[i].b.x,i,2);
eve[++tot]=event(L[i].b.x,i,3);
}
sort(eve+1,eve+tot+1);
Set.clear();
for (int i=1;i<=tot;i++)
{
Curx=eve[i].x;
if (eve[i].f==1)
{
Set.insert(L[eve[i].id]);
// for (ITER j=Set.begin();j!=Set.end();j++) printf("%d ",j->id); printf("\n");
}
else if (eve[i].f==2)
{
ITER l,r;
l=Set.find(L[eve[i].id]);
// for (ITER j=Set.begin();j!=Set.end();j++)printf("%d ",j->id);printf("\n");
r=l; r++;
if (l!=Set.begin())
l--,add(eve[i].id,l->id,++inum);
if (r!=Set.end())
add(r->id,eve[i].id,++inum);
}
else if (eve[i].f==3)
{
Set.erase(L[eve[i].id]);
// for (ITER j=Set.begin();j!=Set.end();j++)printf("%d ",j->id);printf("\n");
}
}
Topo();
icnt=0;
for (int i=1;i<=n;i++) uniq[++icnt]=L[i].a.x,uniq[++icnt]=L[i].b.x;
sort(uniq+1,uniq+icnt+1);
icnt=unique(uniq+1,uniq+icnt+1)-uniq-1;
for (int i=1;i<=n;i++) rank[lst[i]]=i;
SEG.Build(icnt-1);
int ans=n,itmp,id,di,l,r;
for (int i=n;i;i--)
{
id=Q[i].first,di=Q[i].second;
l=Bin(L[id].a.x),r=Bin(L[id].b.x)-1;
if ((di&1)==d)
{
if (di>>1)
{
itmp=SEG.Max(l,r);
if (itmp>rank[id])
ans=i;
}
else
{
itmp=SEG.Min(l,r);
if (itmp<rank[id])
ans=i;
}
}
SEG.Change(l,r,rank[id]);
}
// for (int i=1;i<=icnt-1;i++)
// printf("%d %d\n",SEG.Max(i,i),SEG.Min(i,i));
cl(head); inum=0;
return ans;
}
int main()
{
Point a,b;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n);
for (int i=1;i<=n;i++)
{
read(a.x); read(a.y); read(b.x); read(b.y);
if (b<a) swap(a,b);
L[i]=Line(a,b,i);
}
for (int i=1;i<=n;i++)
read(Q[i].first),read(Q[i].second);
Ans=Solve(1);
for (int i=1;i<=n;i++)
{
swap(L[i].a.x,L[i].a.y); L[i].a.y*=-1;
swap(L[i].b.x,L[i].b.y); L[i].b.y*=-1;
if(L[i].b<L[i].a) swap(L[i].a,L[i].b);
}
Ans=min(Ans,Solve(0));
printf("%d\n",Ans);
for (int i=1;i<=n;i++) printf("%d 0\n",lst[i]);
return 0;
}