CCF CSP 202309-4 阴阳龙

文章讲述了在一个棋盘地图上,如何通过创建有序映射集合来高效计算Dragon出现时每个工人到其最近位置的距离,避免遍历所有工人导致超时。通过判断Dragon到边界和工人位置的关系,仅更新相关映射集合,最后根据Dragon的新位置进行旋转操作。
摘要由CSDN通过智能技术生成

题目

试题编号202309-4
试题名称阴阳龙
时间限制2s
内存限制1GB
问题描述在这里插入图片描述
输入输出在这里插入图片描述
样例1在这里插入图片描述
样例说明在这里插入图片描述

题目分析

题目要注意的小细节很多:

  1. 每次Dragon出现的时候如果Dragon和边界的最小距离要小于等于Dragon到任何工人的位置距离。那么这次Dragon的出现忽略。
  2. 对一个 n ∗ m n*m nm的地图上的任何一个人,要找到每次Dragon出现下位置 ( x , y ) (x,y) (x,y)到最近的工人的距离。每次都遍历取找所有员工,那么会超时。正确的做法是把地图中的横,竖,斜线,反斜线存储成四个映射集合。
    r o w 中各个点的 y 值恒定。 c o l 中各个点的 x 值恒定。 l u ( 斜线 ) 中 x − y 恒定。 u l ( 反斜线 ) 中 x + y 恒定 row中各个点的y值恒定。col中各个点的x值恒定。lu(斜线)中x-y恒定。ul(反斜线)中x+y恒定 row中各个点的y值恒定。col中各个点的x值恒定。lu(斜线)xy恒定。ul(反斜线)x+y恒定
  3. 所以对于每一个员工,都要建立一个映射存储,我用的是 u n o r d e r e d _ m a p < i n t , s e t < p o i n t > > r o w , c o l , l u , u l unordered\_map<int,set<point>>row,col,lu,ul unordered_map<int,set<point>>row,col,lu,ulpoint是结构体,存储员工的编号num,以及坐标x,y。
  4. 每次Dragon出现在 ( x , y ) (x,y) (x,y)的时候先判断下到边界的最小距离 k m m k_{mm} kmm。然后分别判断 r o w [ y ] , c o l [ x ] , l u [ x − y ] , u l [ x + y ] row[y],col[x],lu[x-y],ul[x+y] row[y],col[x],lu[xy],ul[x+y],找到和Dragon最近的工人距离 k m k_{m} km。如果 k m < = k m m k_m<=k_{mm} km<=kmm。就把Dragon的距离为 k m k_{m} km的工人旋转。

AC代码

在这里插入图片描述
不知道为什么每次search的时候要判断下当前的row[y]的集合不为空…我已经在remove中删掉了为空的情况。但是不判断就会运行错误。

#include <bits/stdc++.h>
#define ll long long 
#define rep(i,a,n) for(int i=a;i<n;i++)
#define abs(a) ((a)>0?(a):(-(a)))
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
struct point{
	int x;
	int y;
	int num;
	bool operator<(const point& b)const{
		if(x<b.x)return true;
		else if(x==b.x)return y<b.y;
		return false;
	}
	bool operator==(const point& b)const{
		return x==b.x&&y==b.y;
	}
	point(int _x,int _y):x(_x),y(_y){}
	point(){}
}u[100001];
point e;//dragon 
unordered_map<int,set<point>>row,col,lu,ul;
vector<point>result;
int n,m,p,g,t,x,y,k;
ll ans=0;
int k_m;
int dir[8][2]={{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};
int main(){
	cin>>n>>m>>p>>g;
	auto insert=[&](int i){
		int _x=u[i].x;
		int _y=u[i].y;
		row[_y].insert(u[i]);
		col[_x].insert(u[i]);
		lu[_x-_y].insert(u[i]);
		ul[_x+_y].insert(u[i]);		
	};
	auto remove=[&](int i){
		int _x=u[i].x;
		int _y=u[i].y;
		row[_y].erase(u[i]);
		col[_x].erase(u[i]);
		lu[_x-_y].erase(u[i]);
		ul[_x+_y].erase(u[i]); 	
		if(row[_y].empty())row.erase(_y);
		if(col[_x].empty())col.erase(_x);
		if(lu[_x-_y].empty())lu.erase(_x-_y);
		if(ul[_x+_y].empty())ul.erase(_x+_y);	
	};
	auto search=[&](){
		k_m = 0x7fffffff; 
		x=e.x;
		y=e.y;
		if(row.find(y)!=row.end()){
			auto upper=row[y].upper_bound(e);
			auto lower=row[y].lower_bound(e);
			if(upper==row[y].end()&&lower==row[y].end()&&row[y].size()!=0){
				k_m=min(k_m,abs(x-(row[y].rbegin())->x));
			}
			else{
				if(upper!=row[y].end()){
					k_m=min(k_m,upper->x-x);
				}
				if(lower!=row[y].end()&&lower!=row[y].begin()){
					lower--;
					k_m=min(k_m,x-lower->x);
				}				
			}
		}
		if(col.find(x)!=col.end()){
			auto upper=col[x].upper_bound(e);
			auto lower=col[x].lower_bound(e);
			if(upper==col[x].end()&&lower==col[x].end()&&col[x].size()!=0){
				k_m=min(k_m,abs(y-(col[x].rbegin())->y));
			}
			else{
				if(upper!=col[x].end()){
					k_m=min(k_m,upper->y-y);
				}
				if(lower!=col[x].end()&&lower!=col[x].begin()){
					lower--;
					k_m=min(k_m,y-lower->y);
				}				
			}
		}
		if(lu.find(x-y)!=lu.end()){
			auto upper=lu[x-y].upper_bound(e);
			auto lower=lu[x-y].lower_bound(e);
			if(upper==lu[x-y].end()&&lower==lu[x-y].end()&&lu[x-y].size()!=0){
				k_m=min(k_m,abs(x-(lu[x-y].rbegin())->x));
			}
			else{
				if(upper!=lu[x-y].end()){
					k_m=min(k_m,upper->x-x);
				}
				if(lower!=lu[x-y].end()&&lower!=lu[x-y].begin()){
					lower--;
					k_m=min(k_m,x-lower->x);
				}				
			}
		}
		if(ul.find(x+y)!=ul.end()){
			auto upper=ul[x+y].upper_bound(e);
			auto lower=ul[x+y].lower_bound(e);
			if(upper==ul[x+y].end()&&lower==ul[x+y].end()&&ul[x+y].size()!=0){
				k_m=min(k_m,abs(x-(ul[x+y].rbegin())->x));
			}
			else{
				if(upper!=ul[x+y].end()){
					k_m=min(k_m,upper->x-x);
				}
				if(lower!=ul[x+y].end()&&lower!=ul[x+y].begin()){
					lower--;
					k_m=min(k_m,x-lower->x);
				}				
			}
		}
	};
	auto rotate=[&](){
		result.clear();
		rep(i,0,8){
			int _x=x+dir[i][0]*k_m;
			int _y=y+dir[i][1]*k_m;
			if(row[_y].find(point(_x,_y))!=row[_y].end()){
				int index=(row[_y].find(point(_x,_y)))->num;
				remove(index);
				result.push_back(point(index,i));
			}
		}		
	};
	rep(i,1,p+1){
		cin>>u[i].x>>u[i].y;
		u[i].num=i;
		insert(i);
	}
	while(g--){
		cin>>e.x>>e.y>>t;
		int k_mm=min(e.x-1,min(n-e.x,min(e.y-1,m-e.y)));	
		search();
		if(k_mm<k_m)continue;
		rotate();
		for(auto _t:result){
			int to_direct=(_t.y+t)%8;
			u[_t.x].x=e.x+dir[to_direct][0]*k_m;
			u[_t.x].y=e.y+dir[to_direct][1]*k_m;
			insert(_t.x);
		}
	}
	rep(i,1,p+1)ans^=(1ll*i*u[i].x+u[i].y);
	cout<<ans;
	return 0;
}
/*
3 3 9 1
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
2 2 1

7 7 7 5
4 4
4 6
3 6
2 6
6 2
2 4
7 4
4 4 1
2 2 7
4 4 7
3 4 5
5 5 3

7 7 7 4
4 4
4 6
3 6
2 6
6 2
2 4
7 4
4 4 1
2 2 7
4 4 7
3 4 5


7 7 7 8
4 4
4 6
3 6
2 6
6 2
2 4
7 4
4 4 1
2 2 7
4 4 7
3 4 5
5 5 3
5 2 6
6 3 3
3 6 1

*/
  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值