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

题解:[JOISC 2022] 京都观光

题目传送门

题意分析

考虑从左上角 \((i_1,j_1)\) 走到右下角 \((i_2,j_2)\),只拐一次弯。

008

有两种走法:

  1. 先向右,再向下,距离为:

    \[a_{i_1}(j_2-j_1)+b_{j_2}(i_2-i_1) \]

  2. 先向下,再向右,距离为:

    \[a_{i_2}(j_2-j_1)+b_{j_1}(i_2-i_1) \]

\(1\) 种优于第二种当且仅当:

\[\begin{aligned} a_{i_1}(j_2-j_1)+b_{j_2}(i_2-i_1)&<a_{i_2}(j_2-j_1)+b_{j_1}(i_2-i_1)\\ (a_{i_1}-a_{i_2})(j_2-j_1)&<(b_{j_1}-b_{j_2})(i_2-i_1)\\ \dfrac{a_{i_1}-a_{i_2}}{i_2-i_1}&<\dfrac{b_{j_1}-b_{j_2}}{j_2-j_1}\\ \dfrac{a_{i_1}-a_{i_2}}{i_1-i_2}&>\dfrac{b_{j_1}-b_{j_2}}{j_1-j_2}\\ \end{aligned} \]


因此,对于最终确定的最优路径,\((i_1,j_1)\sim(i_2,j_2)\) 的一个拐点,是拐向一条斜率小的路。

因此可以考虑删掉一些不可能成为拐点的部分,每次找最大差分即可。

找到了之后就可以删除这一行/列并更新差分。

可以使用堆或平衡树维护上述过程,链表维护删除修改即可。


例如对于数据:

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

看一下具体过程。(原图来自于官方题解)

009

AC 代码

时间复杂度:\(\mathcal O((n+m)\log(n+m))\)

//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
typedef long long ll;
constexpr const int N=1e5,M=1e5;
int n,m;
int a[N+1],b[N+1],lst[2];
int del[2][N+1],L[2][N+1],R[2][N+1];
struct node{ll value;int size;int l,r,op;
};
bool operator <(node a,node b){return (ll)a.value*b.size<(ll)b.value*a.size;
}
int main(){/*freopen("test.in","r",stdin);freopen("test.out","w",stdout);*/ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>n>>m;for(int i=1;i<=n;i++){cin>>a[i];}for(int i=1;i<=m;i++){cin>>b[i];}priority_queue<node>q;for(int i=2;i<=n;i++){q.push({a[i]-a[i-1],1,i-1,i,0});L[0][i]=i-1;R[0][i]=i+1;}R[0][n]=0;for(int i=2;i<=m;i++){q.push({b[i]-b[i-1],1,i-1,i,1});L[1][i]=i-1;R[1][i]=i+1;}R[1][m]=0;lst[0]=a[n],lst[1]=b[m];ll ans=0;while(q.size()){node x=q.top();q.pop();int &op=x.op,&size=x.size,&l=x.l,&r=x.r;if(del[op][l]||del[op][r]){continue;}if(!R[op][r]){R[op][L[op][r]]=0;if(!op){lst[0]=a[L[0][r]];}else{lst[1]=b[L[1][r]];}del[op][r]=true;ans+=1ll*lst[op^1]*size;}else{L[op][R[op][r]]=L[op][r];R[op][L[op][r]]=R[op][r];del[op][r]=true;int pl=L[op][r],pr=R[op][r];if(!op){q.push({a[pr]-a[pl],pr-pl,pl,pr,0});}else{q.push({b[pr]-b[pl],pr-pl,pl,pr,1});}}}cout<<ans<<'\n';cout.flush();/*fclose(stdin);fclose(stdout);*/return 0;
}
/*
6 8
3 5 1 9 4 8
3 6 7 1 8 2 5 6
*/
http://www.aitangshan.cn/news/249.html

相关文章:

  • 2025.8.11
  • 2025-08-10 模拟赛总结
  • Day40
  • 2025.08.08 HDU 多校ACM
  • Hexo + NexT主题美化GitHub博客
  • 家用机器人指令跟随训练新数据集发布
  • 【2025.8.11】模拟赛
  • STL set、map
  • 今日总结
  • 8.10XS模拟赛
  • 企业经营分析指南:从供产销研运5大维度,用数据找准优化方向 - 智慧园区
  • 软工8.11
  • 补题祭day1
  • 2-SAT 学习报告
  • ces
  • day38
  • CSP-J 模拟1解析
  • 20250811
  • 《Effective C++》(1,2)
  • 数组
  • CSP-S模拟赛11 总结
  • CSP-S模拟赛12 总结
  • 旋转表达:blender下骨骼重映射的公式推导 bone animation retarget
  • 进度
  • 一名OIER的开始
  • springboot监听redisKey过期 - br
  • 你好我好一切都好 - Karry
  • 数据库操作例题
  • 02010901 表达式和运算符
  • 浏览器面试题及详细答案 88道(01-11) - 详解