(2023-10-30编写)【CSP202309-4】阴阳龙-map+set+模拟

2023-10-30 12:04

本文主要是介绍(2023-10-30编写)【CSP202309-4】阴阳龙-map+set+模拟,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

测试地址: 阴阳龙

题目大意: n × m n\times m n×m的网格上有 p p p个人,每个人都站在一个整数坐标上,且两两位置不同。还有 q q q次“阴阳龙现身”事件,每次事件会选取一个旋转中心,从这个中心出发,向横、竖、斜线上的8个方向寻找最接近的人或边界,然后取出8个位置,将这8个位置上的人(如果有的话)进行某种旋转置换,最后还是回到这8个位置上,具体看题目。求最后所有 p p p个人的位置。 n , m ≤ 1 0 9 , p , q ≤ 1 0 5 n,m\le 10^9, p,q\le 10^5 n,m109,p,q105

做法: 本题需要用到map+set+模拟。
其实这道题的思路口胡起来很简单,就是实现比较复杂。如果给你一条数轴上 n n n个点,每次询问一个点,让你求在这个点左右最接近的点,你很快就会想到用set,而这道题只是把“数轴”换成了行、列和斜线而已。所以我们大可以对每行、每列、每条斜线都维护一个set,这样就能求出在这些方向上最接近的点了,然后就是模拟题目中所说的过程,进行插入、删除等操作即可。不同的斜线可以用 x − y x-y xy x + y x+y x+y来进行区分。
而考虑到网格可能很大,所以再用一个map来维护每行、每列、每条斜线对应的set,只有当被访问到时才建set。这说得像是“map套set”,但实际上在map中查找和在set中查找的操作是分别进行的,所以复杂度只有一个 log ⁡ \log log,整个解法的复杂度应该是一个常数比较大的 O ( q log ⁡ p ) O(q\log p) O(qlogp),肯定够用了。这样我们就解决了这一题。

代码实现:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;int n,m,p,q;struct Point
{Point() {}Point(int _x, int _y, int _id){x=_x;y=_y;id=_id;}int x,y;int id;
}pt[100010];const bool operator < (const Point& a, const Point& b)
{if (a.x!=b.x) return a.x<b.x;else return a.y<b.y;
}map<int,int> setid[4];
vector<set<Point>*> st;void set_insert(int type,int x,Point pnt)
{if (setid[type][x]==0){st.push_back(new set<Point>());setid[type][x]=st.size()-1;}st[setid[type][x]]->insert(pnt);
}void set_delete(int type,int x,Point pnt)
{st[setid[type][x]]->erase(pnt);
}int find_dir[4][2]={{0,4},{6,2},{7,3},{5,1}};
int dir[8][2]={{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}};
int find_res[8][2]; //id, kvoid set_find(int type,int x,Point pnt)
{int id=setid[type][x];if (id==0) return;set<Point>::iterator it_upper=st[id]->upper_bound(pnt);set<Point>::iterator it_lower=st[id]->lower_bound(pnt);if (it_lower!=st[id]->begin()){it_lower--;find_res[find_dir[type][0]][0] = it_lower->id;find_res[find_dir[type][0]][1] = max(abs(it_lower->x - pnt.x), abs(it_lower->y - pnt.y));}if (it_upper!=st[id]->end()){find_res[find_dir[type][1]][0] = it_upper->id;find_res[find_dir[type][1]][1] = max(abs(it_upper->x - pnt.x), abs(it_upper->y - pnt.y));}
}void insert_point(Point pnt)
{int x=pnt.x, y=pnt.y;set_insert(0,x,pnt);set_insert(1,y,pnt);set_insert(2,x-y,pnt);set_insert(3,x+y,pnt);
}void delete_point(Point pnt)
{int x=pnt.x, y=pnt.y;set_delete(0,x,pnt);set_delete(1,y,pnt);set_delete(2,x-y,pnt);set_delete(3,x+y,pnt);
}void find_point(int x,int y)
{for(int i=0;i<8;i++)find_res[i][0]=find_res[i][1]=-1;Point pnt=Point(x,y,0);set_find(0,x,pnt);set_find(1,y,pnt);set_find(2,x-y,pnt);set_find(3,x+y,pnt);
}void solve(int x,int y,int t)
{find_point(x,y);int limit=min(min(x-1,n-x),min(y-1,m-y));int k=limit+1;for(int i=0;i<8;i++){if (find_res[i][1]!=-1 && find_res[i][1]<=limit)k = min(k, find_res[i][1]);}if (k==limit+1) return;for(int i=0;i<8;i++)if (find_res[i][1]==k){int id=find_res[i][0];delete_point(pt[id]);pt[id].x=x+dir[(i+t)%8][0]*k;pt[id].y=y+dir[(i+t)%8][1]*k;}for(int i=0;i<8;i++)if (find_res[i][1]==k){int id=find_res[i][0];insert_point(pt[id]);}
}int main()
{cin >> n >> m >> p >> q;st.push_back(new set<Point>()); //occupy index 0for(int i=1;i<=p;i++){int x,y;cin >> x >> y;pt[i]=Point(x,y,i);insert_point(pt[i]);}for(int i=1;i<=q;i++){int x,y,t;cin >> x >> y >> t;solve(x,y,t);}ll ans=0;for(int i=1;i<=p;i++)ans=((ll)ans)^((ll)i*(ll)pt[i].x+(ll)pt[i].y);cout << ans << endl;return 0;
}

这篇关于(2023-10-30编写)【CSP202309-4】阴阳龙-map+set+模拟的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/307801

相关文章

JSON字符串转成java的Map对象详细步骤

《JSON字符串转成java的Map对象详细步骤》:本文主要介绍如何将JSON字符串转换为Java对象的步骤,包括定义Element类、使用Jackson库解析JSON和添加依赖,文中通过代码介绍... 目录步骤 1: 定义 Element 类步骤 2: 使用 Jackson 库解析 jsON步骤 3: 添

Java中List转Map的几种具体实现方式和特点

《Java中List转Map的几种具体实现方式和特点》:本文主要介绍几种常用的List转Map的方式,包括使用for循环遍历、Java8StreamAPI、ApacheCommonsCollect... 目录前言1、使用for循环遍历:2、Java8 Stream API:3、Apache Commons

利用Python编写一个简单的聊天机器人

《利用Python编写一个简单的聊天机器人》这篇文章主要为大家详细介绍了如何利用Python编写一个简单的聊天机器人,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 使用 python 编写一个简单的聊天机器人可以从最基础的逻辑开始,然后逐步加入更复杂的功能。这里我们将先实现一个简单的

mysql-8.0.30压缩包版安装和配置MySQL环境过程

《mysql-8.0.30压缩包版安装和配置MySQL环境过程》该文章介绍了如何在Windows系统中下载、安装和配置MySQL数据库,包括下载地址、解压文件、创建和配置my.ini文件、设置环境变量... 目录压缩包安装配置下载配置环境变量下载和初始化总结压缩包安装配置下载下载地址:https://d

使用PyQt5编写一个简单的取色器

《使用PyQt5编写一个简单的取色器》:本文主要介绍PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16进制颜色编码,一款跟随鼠标刷新图像的RGB和16... 目录取色器1取色器2PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16

使用Java编写一个文件批量重命名工具

《使用Java编写一个文件批量重命名工具》这篇文章主要为大家详细介绍了如何使用Java编写一个文件批量重命名工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录背景处理1. 文件夹检查与遍历2. 批量重命名3. 输出配置代码片段完整代码背景在开发移动应用时,UI设计通常会提供不

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

30常用 Maven 命令

Maven 是一个强大的项目管理和构建工具,它广泛用于 Java 项目的依赖管理、构建流程和插件集成。Maven 的命令行工具提供了大量的命令来帮助开发人员管理项目的生命周期、依赖和插件。以下是 常用 Maven 命令的使用场景及其详细解释。 1. mvn clean 使用场景:清理项目的生成目录,通常用于删除项目中自动生成的文件(如 target/ 目录)。共性规律:清理操作

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm