https://ac.nowcoder.com/acm/contest/3005/I
又做麻烦了,悲催。。。
将所有星星按x坐标为第一关键字,z为第二关键字排好序
那么一个z=1的星星匹配的是x比它小的,y比他小但又尽可能大的星星
用线段树维护所有的y坐标
如果z=0,直接把y坐标插入线段树
如果z=1,在线段树中找小于它的y坐标,y又最大的那个星星,线段树中删走
题解直接用的set,而且在x相同时先处理z=1再处理z=0更方便。唉。。。
#include<cstdio> #include<algorithm> using namespace std; #define N 100002 struct node { int x,y; }e0[N],e1[N]; int m,has[N]; int sum[N<<2],tot; bool cmp(node p,node q) { return p.x<q.x; } void change(int k,int l,int r,int pos,int x) { sum[k]+=x; if(l==r) return; int mid=l+r>>1; if(pos<=mid) change(k<<1,l,mid,pos,x); else change(k<<1|1,mid+1,r,pos,x); } void query2(int k,int l,int r,int opl,int opr) { if(l>=opl && r<=opr) { tot+=sum[k]; return; } int mid=l+r>>1; if(opl<=mid) query2(k<<1,l,mid,opl,opr); if(opr>mid) query2(k<<1|1,mid+1,r,opl,opr); } int query(int k,int l,int r,int pos) { if(l==r) if(sum[k]) return l; else return 0; int mid=l+r>>1; tot=0; query2(1,1,m,mid+1,pos); if(tot) return query(k<<1|1,mid+1,r,pos); return query(k<<1,l,mid,pos); } int main() { int n,x,y,z,n0=0,n1=0; scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d%d%d",&x,&y,&z); if(z) e1[++n1].x=x,e1[n1].y=y; else e0[++n0].x=x,e0[n0].y=y; has[i]=y; } sort(has+1,has+n+1); m=unique(has+1,has+n+1)-has-1; sort(e0+1,e0+n0+1,cmp); sort(e1+1,e1+n1+1,cmp); e0[n0+1].x=1e9+1; int now0=1,now1=1,i,mx,ans=0; while(now1<=n1 && e1[now1].x<=e0[1].x) now1++; while(now0<=n0) { for(i=now0;i<=n0 && e0[i].x==e0[now0].x;++i) change(1,1,m,lower_bound(has+1,has+m+1,e0[i].y)-has,1); while(now1<=n1 && e1[now1].x<=e0[now0+1].x) { mx=query(1,1,m,lower_bound(has+1,has+m+1,e1[now1].y)-has-1); if(mx) change(1,1,m,mx,-1),ans++; now1++; } now0=i; } printf("%d",ans); return 0; }