题目
Summer Training 06 - Amritapuri 2012 总结
题意:
有很多个房间,之间没有交叉和重叠。求每个房间外面是空地还是别的房间。
题解:
扫描线,将横坐标离散,线段树表示当前横坐标范围内哪些纵坐标是哪些房间。插入新房间时查一下这一段内是哪个房间或空地(因为没有交叉所以查一个点就行),到房间的右边界就把原来查询得到的房间编号覆盖回去。
//Time:1510ms //Memory:21504KB //Length:2303B #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; #define MAXN 200005 #define MAXM 400010 #define MP(x,y) make_pair(x,y) #define FI first #define SE second int tree[MAXN<<2],lazy[MAXN<<2]; void down(int p,int la) { if (la!=-1) { lazy[p<<1]=la; lazy[p<<1|1]=la; tree[p<<1]=la; tree[p<<1|1]=la; lazy[p]=-1; } } void insert(int p,int L,int R,int l,int r,int w) { if (l==L&&r==R) { tree[p]=w; lazy[p]=w; return; } down(p,lazy[p]); int mid=(L+R)>>1; if (r<=mid) insert(p<<1,L,mid,l,r,w); else if (l>mid) insert(p<<1|1,mid+1,R,l,r,w); else { insert(p<<1,L,mid,l,mid,w); insert(p<<1|1,mid+1,R,mid+1,r,w); } tree[p]=-1; } int cal(int p,int L,int R,int k) { if (tree[p]!=-1) return tree[p]; down(p,lazy[p]); int mid=(L+R)>>1; if (k<=mid) return cal(p<<1,L,mid,k); else return cal(p<<1|1,mid+1,R,k); } pair<int,int> pa[MAXM],x[MAXM],y[MAXM]; int lis[MAXM],ans[MAXN]; int bs(int key,int r) { int l=0,mid; while(l<r) { mid=(l+r)/2; if(lis[mid]<key) l=mid+1; else r=mid; } return l; } int main() { //freopen("/home/moor/Code/input","r",stdin); int top,ltop,n; while (scanf("%d",&n)==1) { top=ltop=0; memset(tree,0,sizeof(tree)); memset(lazy,-1,sizeof(lazy)); for(int i=1;i<=n;++i) { scanf("%d%d%d%d",&x[i].FI,&y[i].FI,&x[i].SE,&y[i].SE); pa[top++]=MP(x[i].FI,i); pa[top++]=MP(x[i].SE,-i); lis[ltop++]=y[i].FI; lis[ltop++]=y[i].SE; } sort(lis,lis+ltop); sort(pa,pa+top); ltop=unique(lis,lis+ltop)-lis; for(int i=0;i<top;++i) if(pa[i].SE>0) { int a=bs(y[pa[i].SE].FI,ltop)+1,b=bs(y[pa[i].SE].SE,ltop)+1; ans[pa[i].SE]=cal(1,1,ltop,a); insert(1,1,ltop,a,b,pa[i].SE); } else { int a=bs(y[-pa[i].SE].FI,ltop)+1,b=bs(y[-pa[i].SE].SE,ltop)+1; insert(1,1,ltop,a,b,ans[-pa[i].SE]); } for(int i=1;i<=n;++i) printf("%d\n",ans[i]-1); } return 0; }