D - Santa Claus 2
题目链接:https://atcoder.jp/contests/abc385/tasks/abc385_d
题意:
一个人根据序列不断地走,当他沿路经过某个房子时需要计数,输出最后位置以及经历的房子数
思路:
由于坐标范围给的非常大,所以暴力不行,也就是开二维数组的方式更不行
因此怎么样去表示房子的位置是关键
不妨开两个map<int,set
每一列 - > 这一列房子的行坐标的集合
不难发现走路的过程其实就是在x或y一维直线上走动,因此可以规定左端点和右端点,考虑set二分
在操作时,分别对初始的x/y坐标和走动后的x/y坐标进行二分,然后把走过的房子分别在两个map中消除
代码实现方面要注意:set二分返回的是迭代器,当遍历迭代器时,使用erase方法需要删除的是返回的迭代器,这样通过赋值迭代器的方式才能前进
int res;
void solve(){
int n,m,stx,sty;cin>>n>>m>>stx>>sty;
map<int,set<int>>row,col;
for(int i=1;i<=n;i++){
int x,y;cin>>x>>y;
if(x==stx&&y==sty){
res++;continue;
}
row[y].insert(x);
col[x].insert(y);
}
int x=stx,y=sty;
for(int i=1;i<=m;i++){
char d;int c;cin>>d>>c;
if(d=='U'||d=='D'){
if(d=='D')c=-c;
int l=min(y,y+c),r=max(y,y+c);
auto t1=col[x].lower_bound(l);
auto t2=col[x].upper_bound(r);
for(auto j=t1;j!=t2;){
int num=(*j);
res++;
row[num].erase(x);
j=col[x].erase(j);
}
y=y+c;
}else{
if(d=='L')c=-c;
int l=min(x,x+c),r=max(x,x+c);
auto t1=row[y].lower_bound(l);
auto t2=row[y].upper_bound(r);
for(auto j=t1;j!=t2;){
int num=(*j);
res++;
col[num].erase(y);
j=row[y].erase(j);
}
x=x+c;
}
}
cout<<x<<' '<<y<<' '<<res<<endl;
}

浙公网安备 33010602011771号