当前位置: 首页 > news >正文

题解:洛谷 P10801([CEOI 2024] 海战)

1. Description

捷克海军司令官翁德拉刚刚晋升为大元帅,正享受着新职位的安稳,却突然被政府通知海军将被裁撤。
翁德拉决心证明捷克海军的重要性。他通过间谍得知,一场四国海军巨舰对决即将展开。如果能赢得这场战役,无疑能向政府有力地展示海军价值。
然而,捷克海军既无战舰也无港口。但翁德拉想到,如果他的间谍能夺取几艘参战舰艇,或许还有一线生机。关键是,如何预知哪些船能在这场海战中幸存下来呢?
海战规则如下:

  • 战前,第 \(i\) 艘战舰位于坐标 \((x_i, y_i)\) 处,其中 \(x_i\)\(y_i\) 均为偶数。每艘战舰隶属于北方、南方、东方或西方舰队之一。
  • 海战分回合进行。每回合:
    • 每艘战舰同时向其所属舰队方向移动一格。
    • 如果两艘或以上战舰占据同一格,它们将相撞沉没,从海图上消失。
  • 当不再发生碰撞时,海战结束。存活的战舰是指海战结束后仍留在海图上的战舰。
    各舰队战舰的移动方向及坐标变化如下:
  • 北方舰队:\(y\) 坐标减 \(1\)
  • 南方舰队:\(y\) 坐标加 \(1\)
  • 东方舰队:\(x\) 坐标加 \(1\)
  • 西方舰队:\(x\) 坐标减 \(1\)

2. Solution

首先,暴力做法不难想到,暴力枚举所有战舰对,计算出它们相撞的时间,然后扔进一个小根堆中依次处理即可,时间复杂度 \(O(n^2)\)
我们考虑优化这个做法,去除掉一定不会用到的战舰对。
考虑一艘向南的战舰 \(i\),一艘向东的战舰 \(j\),如果它们会在时间 \(t\) 相撞,那么满足 \(x_i+t=x_j,y_i+t=y_j\),简单整理就有 \(x_i-y_i=x_j-y_j\)
就是说,这两艘战舰想要相撞,必然就有横纵坐标之差相等,所以我们按照横纵坐标差将战舰分类。但是这样并没有实际作用,我们仍然需要进一步考虑。
如果可以相撞,一定有 \(t=x_i-x_j\),我们发现,如果将这一类的战舰按照 \(x\) 排序,一定有相邻的战舰对优于不相邻的战舰对,那么就可以将有用的战舰对优化到 \(O(n)\) 了。
其余 \(5\) 种组合,读者可自行推导,这里给出结论:
向北和向东:\(x-y\) 相等,按照 \(x\) 坐标排序。
向北和向西:\(x+y\) 相等,按照 \(x\) 坐标排序。
向北和向南:\(x\) 相等,按照 \(y\) 坐标排序。
向东和向西:\(y\) 相等,按照 \(x\) 坐标排序。
向东和向南:\(x+y\) 相等,按照 \(x\) 坐标排序。
向西和向南:\(x-y\) 相等,按照 \(x\) 坐标排序。
可以使用 set 维护同一类的战舰。
在小根堆处理的时候,我们每一次取出堆顶的战舰对,判断是否相撞,然后在对应的 set 中删除这两艘战舰,最后加入新的可能的战舰对即可,不难判断这样的时间复杂度是 \(O(n\log n)\) 的。

3. Code

/*by ChenMuJiu*/
/*略去缺省源与快读快写*/
const int N=2e5+5,dx[]={0,1,-1,0},dy[]={-1,0,0,1},inf=0x3f3f3f3f;
int n;
int x[N],y[N],d[N],t[N];
struct Node{int first,second,idx;bool operator <(const Node &T)const{if(first^T.first)return first<T.first;return second<T.second;}
};
set<Node>idx[4][4];
struct event{int t,x,y;bool operator >(const event &T)const{return t>T.t;}
};
priority_queue<event,vector<event>,greater<event>>q;
int cal(int i,int j){if(d[i]==d[j])return -1;int t=-1;if(dx[d[i]]!=dx[d[j]])t=(x[i]-x[j])/(dx[d[j]]-dx[d[i]]);if(dy[d[i]]!=dy[d[j]])t=(y[i]-y[j])/(dy[d[j]]-dy[d[i]]);if(t<0)return -1;if(x[i]+t*dx[d[i]]!=x[j]+t*dx[d[j]])return -1;if(y[i]+t*dy[d[i]]!=y[j]+t*dy[d[j]])return -1;return t;
}
void delet(int id){set<Node>::iterator it;if(d[id]==0){it=idx[0][1].lower_bound({x[id]-y[id],x[id],id});if(it!=idx[0][1].begin()&&next(it)!=idx[0][1].end()){int t=cal(prev(it)->idx,next(it)->idx);if(~t)q.push({t,prev(it)->idx,next(it)->idx});}idx[0][1].erase(it);it=idx[0][2].lower_bound({x[id]+y[id],x[id],id});if(it!=idx[0][2].begin()&&next(it)!=idx[0][2].end()){int t=cal(prev(it)->idx,next(it)->idx);if(~t)q.push({t,prev(it)->idx,next(it)->idx});}idx[0][2].erase(it);it=idx[0][3].lower_bound({x[id],y[id],id});if(it!=idx[0][3].begin()&&next(it)!=idx[0][3].end()){int t=cal(prev(it)->idx,next(it)->idx);if(~t)q.push({t,prev(it)->idx,next(it)->idx});}idx[0][3].erase(it);}else if(d[id]==1){it=idx[0][1].lower_bound({x[id]-y[id],x[id],id});if(it!=idx[0][1].begin()&&next(it)!=idx[0][1].end()){int t=cal(prev(it)->idx,next(it)->idx);if(~t)q.push({t,prev(it)->idx,next(it)->idx});}idx[0][1].erase(it);it=idx[1][2].lower_bound({y[id],x[id],id});if(it!=idx[1][2].begin()&&next(it)!=idx[1][2].end()){int t=cal(prev(it)->idx,next(it)->idx);if(~t)q.push({t,prev(it)->idx,next(it)->idx});}idx[1][2].erase(it);it=idx[1][3].lower_bound({x[id]+y[id],x[id],id});if(it!=idx[1][3].begin()&&next(it)!=idx[1][3].end()){int t=cal(prev(it)->idx,next(it)->idx);if(~t)q.push({t,prev(it)->idx,next(it)->idx});}idx[1][3].erase(it);}else if(d[id]==2){it=idx[0][2].lower_bound({x[id]+y[id],x[id],id});if(it!=idx[0][2].begin()&&next(it)!=idx[0][2].end()){int t=cal(prev(it)->idx,next(it)->idx);if(~t)q.push({t,prev(it)->idx,next(it)->idx});}idx[0][2].erase(it);it=idx[1][2].lower_bound({y[id],x[id],id});if(it!=idx[1][2].begin()&&next(it)!=idx[1][2].end()){int t=cal(prev(it)->idx,next(it)->idx);if(~t)q.push({t,prev(it)->idx,next(it)->idx});}idx[1][2].erase(it);it=idx[2][3].lower_bound({x[id]-y[id],x[id],id});if(it!=idx[2][3].begin()&&next(it)!=idx[2][3].end()){int t=cal(prev(it)->idx,next(it)->idx);if(~t)q.push({t,prev(it)->idx,next(it)->idx});}idx[2][3].erase(it);}else{it=idx[0][3].lower_bound({x[id],y[id],id});if(it!=idx[0][3].begin()&&next(it)!=idx[0][3].end()){int t=cal(prev(it)->idx,next(it)->idx);if(~t)q.push({t,prev(it)->idx,next(it)->idx});}idx[0][3].erase(it);it=idx[1][3].lower_bound({x[id]+y[id],x[id],id});if(it!=idx[1][3].begin()&&next(it)!=idx[1][3].end()){int t=cal(prev(it)->idx,next(it)->idx);if(~t)q.push({t,prev(it)->idx,next(it)->idx});}idx[1][3].erase(it);it=idx[2][3].lower_bound({x[id]-y[id],x[id],id});if(it!=idx[2][3].begin()&&next(it)!=idx[2][3].end()){int t=cal(prev(it)->idx,next(it)->idx);if(~t)q.push({t,prev(it)->idx,next(it)->idx});}idx[2][3].erase(it);}
}
signed main(){read(n);for(int i=1;i<=n;i++){read(x[i]),read(y[i]);char c=getchar();while(c!='N'&&c!='E'&&c!='W'&&c!='S')c=getchar();if(c=='N')d[i]=0;else if(c=='E')d[i]=1;else if(c=='W')d[i]=2;else d[i]=3;if(d[i]==0){idx[0][1].insert({x[i]-y[i],x[i],i});idx[0][2].insert({x[i]+y[i],x[i],i});idx[0][3].insert({x[i],y[i],i});}else if(d[i]==1){idx[0][1].insert({x[i]-y[i],x[i],i});idx[1][2].insert({y[i],x[i],i});idx[1][3].insert({x[i]+y[i],x[i],i});}else if(d[i]==2){idx[0][2].insert({x[i]+y[i],x[i],i});idx[1][2].insert({y[i],x[i],i});idx[2][3].insert({x[i]-y[i],x[i],i});}else{idx[0][3].insert({x[i],y[i],i});idx[1][3].insert({x[i]+y[i],x[i],i});idx[2][3].insert({x[i]-y[i],x[i],i});}}for(int i=0;i<4;i++){for(int j=i+1;j<4;j++){auto it=idx[i][j].begin();while(it!=idx[i][j].end()){if(next(it)!=idx[i][j].end()){int t=cal(next(it)->idx,it->idx);if(~t)q.push({t,next(it)->idx,it->idx});}it++;}}}memset(t,0x3f,sizeof(t));while(!q.empty()){auto tmp=q.top();q.pop();if(t[tmp.x]!=inf&&t[tmp.x]!=tmp.t)continue;if(t[tmp.y]!=inf&&t[tmp.y]!=tmp.t)continue;if(t[tmp.x]==inf){t[tmp.x]=tmp.t;delet(tmp.x);}if(t[tmp.y]==inf){t[tmp.y]=tmp.t;delet(tmp.y);}}for(int i=1;i<=n;i++)if(t[i]==inf)write(i),Nxt;
}
http://www.jsqmd.com/news/330785/

相关文章:

  • 优先级电源多路复用器:TPS212x 无缝切换技术的工作原理与典型应用深度解析
  • 智能制造质量控制AI系统的微服务架构:AI应用架构师的拆分与通信实践
  • 使用 Rust 实现零成本抽象:提升性能的关键模式
  • 构建高可用微服务架构:Istio 服务网格故障恢复策略
  • AI应用架构师的企业虚拟化转型创新型方案
  • task3的详细思路与结构
  • 【claude】Claude Skills 实战指南:从安装到自定义
  • 数据立方体在电商用户行为分析中的实战应用
  • 人工智能伦理速成指南:如何在不写一行代码的情况下成为AI治理专家
  • 408真题解析-2010-29-操作系统-页式存储管理
  • Python 异步编程完全指南:从 asyncio 到高性能并发
  • Web性能优化实战:利用Webpack进行代码分割与懒加载
  • Dapper轻量级扩展库SmartDapper
  • macOS 邮件客户端设置:高效管理多个邮箱账户
  • 机器学习项目:Python 淘宝商品数据分析系统 预测算法 Django框架(Selenium爬虫+线性回归预测+Echarts大屏 源码)✅
  • 2026.2.1
  • 【开题答辩全过程】以 高校食堂餐饮管理系统的设计与实现为例,包含答辩的问题和答案
  • 机器学习:Python音乐推荐平台 Django框架 TensorFlow推荐 融合深度学习与协同过滤推荐算法 千千音乐爬虫 大数据实战✅
  • 大数据领域数据中台的安全架构设计
  • 【开题答辩全过程】以 基于python网络安全知识在线答题系统为例,包含答辩的问题和答案
  • 开题报告 高考志愿助手APP
  • DevOps流水线安全加固:GitHub Actions漏洞扫描与修复
  • 开题报告 高校学生成绩管理系统
  • 智能弹性互联网架构推动企业数字化转型优化研发闭环提升系统高可用性与创新能力 - 指南
  • DevOps流水线设计:Jenkins与GitLab CI/CD对比实践
  • 解密区块链跨链技术:Polkadot 与 Cosmos 架构对比
  • 开题报告 高校文化创意信息服务系统开发
  • 区块链智能合约安全审计:Solidity常见漏洞及防范措施
  • 开题报告 高校医务管理系统的设计与开发
  • GitOps工作流实战:ArgoCD实现Kubernetes持续交付