[JOISC 2017 Day1] 开荒者
一、题目
二、解法
首先考虑一维的情况,设平面上的草位置分别是 ,那么答案是:
我们枚举上下方向的风,然后对每行独立做,时间复杂度
可以把行离散化成若干个左闭右开的区间,每个区间内草的分布是相同的,可以统一计算,时间复杂度
有一个关键的 是:如果不考虑边界,上下方向吹一次得到的网格图是同构的。那么我们可以枚举上下吹的总次数 ,然后把原图向下吹 次,然后在 这些行中选取连续的 行就得到了目标的矩形。
发现是一个长度为 的滑动窗口问题,需要对 这三部分分别维护单调队列,然后枚举区间左端点计算答案,那么时间复杂度
现在要把 拿出时间复杂度中,一个想法是减少 的取值数量,发现只有这些 是有用的:
- 能覆盖完整个网格,最小的 (按照一维的方式计算得出)
- 对于任意 , 吹到了下边界, 吹到的上边界,需要的次数
- 对于任意 , 和 在中间碰头所需要的次数
所以 的取值个数是 ,我们预处理出行的区间 合并的结果 (还是要三部分),枚举 之后先离散化,然后用 得到每个行合并的结果,再跑单调队列即可,时间复杂度
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int M = 605;
#define int long long
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int r,c,n,m,ans,b[M];
struct node{int x,y,z;}a[M],f[M][M],g[M];
struct zxy
{
int h,t,s[M],v[M];
zxy() {t=0;h=1;}
void push(int x,int y)
{
for(;h<=t && v[t]<=y;t--);
s[++t]=x;v[t]=y;
}
void pop(int x)
{
for(;h<=t && s[h]<=x;h++);
}
int top() {return v[h];}
};
int calc(int L)
{
m=0;
for(int i=1,j=1;i<=n || j<=n;)
{
if(j>n || (i<=n && a[i].x<=a[j].x+L))
b[++m]=a[i++].x;
else b[++m]=a[j++].x+L+1;
}
m=unique(b+1,b+1+m)-b-1;
for(int i=1,j=1,k=1;i<=m;g[i++]=f[j][k])
{
for(;j<n && a[j].x+L<b[i];j++);
for(;k<n && a[k+1].x<=b[i];k++);
}
int mi=c+c;zxy X,Y,Z;
for(int i=1,j=1;i<=m;i++)
{
for(;j<=m && b[i]+r>b[j];j++)
X.push(j,g[j].x),Y.push(j,g[j].y),Z.push(j,g[j].z);
if(j>m) break;
mi=min(mi,max(X.top()+Z.top(),Y.top()));
X.pop(i);Y.pop(i);Z.pop(i);
}
return mi;
}
signed main()
{
r=read();c=read();n=read();ans=r+c;
for(int i=1;i<=n;i++)
a[i].x=read(),a[i].y=read();
sort(a+1,a+1+n,[&](node u,node v)
{return u.x<v.x;});
for(int i=1;i<=n;i++)
{
set<int> s;
for(int j=i;j<=n;j++)
{
s.insert(a[j].y);m=0;
for(int x:s) b[++m]=x;
f[i][j]={b[1]-1,0,c-b[m]};
for(int k=1;k<m;k++)
f[i][j].y=max(f[i][j].y,b[k+1]-b[k]-1);
}
}
int L=a[1].x-1+r-a[n].x;
for(int i=1;i<n;i++) L=max(L,a[i+1].x-a[i].x-1);
ans=L+calc(L);
for(int i=1,t=0;i<=n;i++) for(int j=1;j<=n;j++)
{
if((t=a[i].x-a[j].x-1)>L)
ans=min(ans,t+calc(t));
if((t=r-a[i].x+a[j].x-1)>L)
ans=min(ans,t+calc(t));
}
printf("%lld\n",ans);
}
分类:
其他-----时间复杂度
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
2021-06-10 CF280D k-Maximum Subsequence Sum