先对n个点分类,然后按题意要求构造,构造的时候判断这个点的右上方之前是否有点,判断可以用线段树来操作。
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<map> #include<algorithm> using namespace std; const int maxn=200000+10; vector<int>g[2*maxn],FX,FY; int w[maxn]; struct X { int x,y,id; }s[maxn],tmp[maxn]; int n,Max; int segtree[2*maxn]; bool cmp(const X&a,const X&b) {return a.x<b.x;} void quary(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) {Max=max(Max,segtree[rt]); return ;} int m=(l+r)/2; if(L<=m) quary(L,R,l,m,2*rt); if(R>m) quary(L,R,m+1,r,2*rt+1); } void update(int pos,int val,int l,int r,int rt) { if(l==r&&l==pos) { segtree[rt]=val; return; } int m=(l+r)/2; if(pos<=m) update(pos,val,l,m,2*rt); else update(pos,val,m+1,r,2*rt+1); segtree[rt]=max(segtree[2*rt],segtree[2*rt+1]); } int main() { scanf("%d",&n); FX.clear(); FY.clear(); for(int i=1;i<=n;i++) scanf("%d%d",&s[i].x,&s[i].y); for(int i=1;i<=n;i++) scanf("%d",&w[i]); sort(s+1,s+1+n,cmp); for(int i=1;i<=n;i++) g[s[i].y-s[i].x+200000].push_back(i); bool fail=0; map<int,int>h; h.clear(); memset(segtree,-1,sizeof segtree); for(int i=1;i<=n;i++) { if(h[w[i]]==g[w[i]+200000].size()) {fail=1;break;} int id=g[w[i]+200000][h[w[i]]]; Max=-1; quary(s[id].x,100000,0,100000,1); if(Max>=s[id].y){fail=1;break;} update(s[id].x,s[id].y,0,100000,1); int tmpx=s[id].x,tmpy=s[id].y; FX.push_back(tmpx); FY.push_back(tmpy); h[w[i]]++; } if(fail==0) { printf("YES\n"); for(int i=0;i<FX.size();i++) printf("%d %d\n",FX[i],FY[i]); } else printf("NO\n"); return 0; }