CodeForces 596C Wilbur and Points

先对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
");
        for(int i=0;i<FX.size();i++) printf("%d %d
",FX[i],FY[i]);
    }
    else printf("NO
");
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/5469154.html