CodeForces 19D Points(线段树+map)
Posted 专注如一
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces 19D Points(离散化+线段树+单点更新)
Codeforces 1140F Extending Set of Points 线段树 + 按秩合并并查集 (看题解)