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;
}
posted @ 2025-03-27 20:34  Marinaco  阅读(20)  评论(0)    收藏  举报
//雪花飘落效果