首页 > 代码库 > CodeForces 19D Points(线段树+map)

CodeForces 19D Points(线段树+map)

  开始想不通,后来看网上说是set,就有一个想法是对每个x建一个set。。。然后又想直接建立两重的set就好,最后发现不行,自己想多了。。。 
  题意是给你三种操作:add (x y) 平面添加(x y)这个点 
remove (x y)平面删除(x y)这个点 
find (x y) 查找(x y)这个点严格的右上方中最左边的点,有多个就再找最下方的点,输出

 

  其实想通了还是比较简单的,我的想法就是对于x先排序再对y排序,这样建一颗线段树,用处在于:添加和删除都可以当成单点更新,只需要记录最大值就好。find时当用map的upper_bound()找到大于x的位置时,可以直接自顶向下搜到范围内大于当前y值(最大值就在这儿用)得最靠前的位置,因为是排序了的,所以最靠前最小。但是范围太大得离散化,我用的是map离散化,另一个二维map找到当前点是树上的第几个点。 
  注意这儿当没有添加操作时,不能建树,因为这样就会出现 Create(1,0,1)。。。一直爆空间,我还以为map被卡了

 

#include<set>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#include<string>#include<cstdio>#include<cstring>#include<stdlib.h>#include<iostream>#include<algorithm>using namespace std;#define eps 1E-8/*注意可能会有输出-0.000*/#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0#define mul(a,b) (a<<b)#define dir(a,b) (a>>b)typedef long long ll;typedef unsigned long long ull;typedef pair<int ,int > pii;const int Inf=1<<28;const double Pi=acos(-1.0);const int Max=200010;const int Max2=200010<<2;char str[Max][10];int xx1[Max],yy1[Max],nnow;map<int,int> mpos;//找到第一个大于需要值的最左边的位置map<pii,int> mp;//离散化map<pii,int>::iterator it;map<int,int>::iterator iit;int segtr[Max2],tem[Max2],ans,flag;int nmax(int a,int b){    return a>b?a:b;}void Upnow(int now,int next){    segtr[now]=nmax(segtr[next],segtr[next|1]);    return;}void Create(int sta,int enn,int now){    if(sta==enn)    {        segtr[now]=-1;        return;    }    int mid=dir(sta+enn,1);    int next=mul(now,1);    Create(sta,mid,next);    Create(mid+1,enn,next|1);    Upnow(now,next);    return;}void Update(int sta,int enn,int now,int x,int y){    if(sta==enn&&sta==x)    {        segtr[now]=y;       nnow=now;        return;    }    int mid=dir(sta+enn,1);    int next=mul(now,1);    if(mid>=x)        Update(sta,mid,next,x,y);    else        Update(mid+1,enn,next|1,x,y);    Upnow(now,next);    return;}void Query(int sta,int enn,int now,int x,int y)//找到范围内大于y的最前面的值(基本可以看做最小值){    if(sta==enn)    {            ans=now;            flag=0;            return;    }    int mid=dir(sta+enn,1);    int next=mul(now,1);    if(flag&&mid>=x&&segtr[next]>y)//这儿判断保证了的效率        Query(sta,mid,next,x,y);    if(flag&&segtr[next|1]>y)        Query(mid+1,enn,next|1,x,y);    return;}int main(){    int n,coun;    while(~scanf("%d",&n))    {        nnow=0;        coun=1;        mpos.clear();        mp.clear();        for(int i=0;i<n;i++)        {            scanf("%s %d %d",str[i],&xx1[i],&yy1[i]);        if(str[i][0] == a)        {            mp[make_pair(xx1[i],yy1[i])]=0;//二维map        }        }        for(it=mp.begin();it!=mp.end();++it)        {            it->second=coun++;//二维map存应该是树上的第几个节点            if(!mpos.count(it->first.first))            mpos[it->first.first]=coun-1;        }        coun--;        if(coun)//一定要注意count>0啊        Create(1,coun,1);        for(int i=0;i<n;i++)        {        if(str[i][0] == a)        {        Update(1,coun,1,mp[make_pair(xx1[i],yy1[i])],yy1[i]);        tem[nnow]=xx1[i];        }        else if(str[i][0] == r)        {        Update(1,coun,1,mp[make_pair(xx1[i],yy1[i])],-1);        tem[nnow]=xx1[i];        }        else        {        ans=-1;        flag=1;        iit=mpos.upper_bound(xx1[i]);        if(iit==mpos.end())        {            printf("-1\n");            continue;        }        Query(1,coun,1,iit->second,yy1[i]);        if(ans==-1)            printf("-1\n");        else            printf("%d %d\n",tem[ans],segtr[ans]);        }        }    }    return 0;}

 

CodeForces 19D Points(线段树+map)