CF EDU 133 C - Robot in a Hallway
作者:互联网
st表 or 后缀和 优化dp
题意
有一个两行 n 列的网格,每个格子有一个解锁时间 \(a[i][j]\) (注意这个是解锁的时间,最早到达该点的时间要 + 1), 过了这个时间才能走进这个格子。每秒可以选择上下左右移一格或者不动,求从 (0, 0) 出发恰好每个格子走一次的最短时间
思路
只有三种可能
可预处理出走蛇形走到 (i, j) 的时间 \(h[i][j]\)
走蓝线的时间为 走蓝线区间不停顿的时间 - 在某个格子等待的最长时间
以图 3 为例,可以给格子按
标号 id
设走到 \((i-1,j)\) 后之后都按 3 的蓝线走,则蓝线时间为
\(id[i][0]-id[i-1][1]+max(0,a[k][j]-(h[i-1][1]+id[k][j]-id[i-1][1]))\)
所以用 st 表维护 \(a[k][j]-id[k][j]\) 的最大值即可 (也可预处理出上下两行的后缀和,复杂度会少一个log)
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
typedef pair<int, int> PII;
const int N = 4e5 + 10, M = 20;
int h[N][2], a[N][2];
int id[N][2];
int n;
void presolve()
{
h[0][0] = 0;
for (int k = 1; k < 2 * n; k++)
{
int i = k / 2;
if (k % 4 == 0)
h[i][0] = max(h[i-1][0] + 1, a[i][0]);
else if (k % 4 == 1)
h[i][1] = max(h[i][0] + 1, a[i][1]);
else if (k % 4 == 2)
h[i][1] = max(h[i-1][1] + 1, a[i][1]);
else
h[i][0] = max(h[i][1] + 1, a[i][0]);
}
}
int hs(int idx, int op)
{
int i, j;
if (op == 0)
{
j = idx / n;
if (j == 0)
i = idx;
else
i = 2 * n - 1 - idx;
}
else
{
j = (idx / n) ^ 1;
if (j == 1)
i = idx;
else
i = 2 * n - 1 - idx;
}
return a[i][j] - id[i][j];
}
template<typename T> struct ST
{
ST(int n, int op)
{
siz = n;
maxv.resize(n+1);
int t = __lg(n) + 1;
for(int i=0;i<n;i++) maxv[i].resize(t);
for(int i = 0; i < n; i++) maxv[i][0] = hs(i, op);
for(int j = 1; j < t; j++)
for(int i = 0; i < n - (1<<j)+1; i++)
maxv[i][j] = max(maxv[i][j-1], maxv[i+(1 << (j-1))][j-1]);
}
T getmax(int l,int r)
{
int k = __lg(r-l+1);
return max(maxv[l][k],maxv[r-(1<<k)+1][k]);
}
private:
int siz = 0;
vector<vector<T>> maxv;
};
int solve(int op)
{
for (int i = 0; i < n; i++)
{
id[i][op] = i;
id[i][op^1] = 2 * n - 1 - i;
}
ST<int> s(2*n, op);
int ans;
if (op == 0)
ans = 2 * n - 1 + max(0, s.getmax(1, 2 * n - 1));
else
ans = 2e9;
int first = op ? 1 : 2;
for (int i = first; i < n; i += 2)
{
int l = i, r = 2 * n - i - 1;
int now = h[i-1][op] + id[i][op^1] - id[i-1][op] + max(0, s.getmax(l, r) + id[i-1][op] - h[i-1][op]);
ans = min(ans, now);
}
return ans;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while(T--)
{
cin >> n;
for (int j = 0; j < 2; j++)
{
for (int i = 0; i < n; i++)
{
int x;
cin >> x;
a[i][j] = x + 1;
}
}
a[0][0] = 0;
presolve();
int ans = min(solve(0), solve(1));
cout << ans << endl;
}
return 0;
}
标签:Hallway,idx,int,Robot,else,133,ans,id,op 来源: https://www.cnblogs.com/hzy717zsy/p/16583209.html