首页 > 其他分享 >CF538G Berserk Robot 题解

CF538G Berserk Robot 题解

时间:2024-07-29 19:29:21浏览次数:6  
标签:std return get int 题解 nr nl CF538G Berserk

Description

有一个机器人,第 \(0\) 秒时在 \((0,0)\) 位置。

机器人会循环执行一个长度为 \(l\) 的指令序列,每秒执行一个指令。

指令有 ULDR 四种,分别代表向上/左/下/右移动一格。

你不知道这个指令序列具体是什么,但是你知道 \(n\) 条信息,第 \(i\) 条信息为「第 \(t_i\) 秒时机器人在 \((x_i,y_i)\)」,保证 \(t\) 递增。

你需要构造一个满足这些信息的指令序列,或判断不存在。

\(n \le 2 \times 10^5\),\(l \le 2 \times 10^6\),\(t_i,|x_i|,|y_i| \le 10^{18}\)。

Solution

注意到这里每次移动 \(x,y\) 会互相影响,而不是独立的,考虑把原图转 \(45^{\circ}\) 即点 \((x,y)\) 变为 \((x+y,x-y)\),这样操作就变为 \((1,1),(1,-1),(-1,1),(-1,-1)\)。

这样已经可以做了,但 \(1,-1\) 这类操作不够优美,考虑让 \((x,y)\) 变为 \(\left(\frac{y+x+t}{2},\frac{y-x+t}{2}\right)\),操作就只有 \((1,1),(1,0),(0,1),(0,0)\),这样题目就简化很多了。

先考虑 \(x\) 的情况,对于 \(y\) 同理。

不妨设 \(s_i\) 表示前 \(i\) 个指令对 \(x\) 的贡献值,对于一组信息 \((t_i,x_i)\),\(r_i=t_i\bmod l,k_i=\left\lfloor\frac{t_i}{l}\right\rfloor\),一定满足 \(x_i=s_{r_i}+k_is_l\),所以\(s_{r_i}=x_i-k_is_l\)。

考虑按照 \(r_i\) 排序,容易发现按照 \(r\) 把 \([1,l]\) 分成若干块,对于块内的操作可以随便排序,所以 \(0\leq (x_{i+1}-k_{i+1}s_l)-(x_{i}-k_is_l)\leq r_{i+1}-r_{i}\),这里为了让 \([1,r_1]\) 和 \([r_n+1,l]\) 这两个块也考虑到,可以加入 \(k=0,r=0,x=0\) 和 \(k=-1,r=l,x=0\) 这两组信息。

通过解不等式就可以得到 \(s_l\) 的范围,然后随便取一个 \(s_l\) 的可能取值对于每个块分别考虑就可以构造出答案了。

时间复杂度:\(O(n\log n+l)\)。

Code

#include <bits/stdc++.h>

#define int int64_t

const int kMaxN = 2e5 + 5, kMaxL = 2e6 + 5;

int n, l;
bool ans[kMaxL][2];
std::tuple<int, int, int, int> a[kMaxN];

char getch(bool o1, bool o2) {
  if (!o1 && !o2) return 'D';
  else if (!o1 && o2) return 'L';
  else if (o1 && !o2) return 'R';
  else return 'U';
}

int cei(int x, int k) {
  if (k < 0) x = -x, k = -k;
  if (x >= 0) return (x + k - 1) / k;
  else return -((-x) / k);
  // return ceil((long double)x / k);
}

int flr(int x, int k) {
  if (k < 0) x = -x, k = -k;
  if (x >= 0) return x / k;
  else return -((-x + k - 1) / k);
  // return floor((long double)x / k);
}

void dickdreamer() {
  std::cin >> n >> l;
  for (int i = 1; i <= n; ++i) {
    int t, x, y;
    std::cin >> t >> x >> y;
    if ((x + y - t) & 1) return void(std::cout << "NO\n");
    a[i] = {t % l, t / l, (y + x + t) / 2, (y - x + t) / 2};
  }
  a[++n] = {0, 0, 0, 0}, a[++n] = {l, -1, 0, 0};
  std::sort(a + 1, a + 1 + n);
  int L = 0, R = l;
  for (int i = 1; i < n; ++i) {
    int k = std::get<1>(a[i]) - std::get<1>(a[i + 1]);
    int nl = std::get<2>(a[i]) - std::get<2>(a[i + 1]);
    int nr = nl + std::get<0>(a[i + 1]) - std::get<0>(a[i]);
    assert(nl <= nr);
    if (!k && (nl > 0 || nr < 0)) return void(std::cout << "NO\n");
    if (k > 0)
      L = std::max(L, cei(nl, k)), R = std::min(R, flr(nr, k));
    else if (k < 0)
      L = std::max(L, cei(nr, k)), R = std::min(R, flr(nl, k));
  }
  if (L > R) return void(std::cout << "NO\n");
  for (int i = 1; i < n; ++i) {
    int det = (std::get<2>(a[i + 1]) - L * std::get<1>(a[i + 1])) -
              (std::get<2>(a[i]) - L * std::get<1>(a[i]));
    assert(det >= 0);
    int nl = std::get<0>(a[i]) + 1, nr = std::get<0>(a[i]) + det;
    for (int j = nl; j <= nr; ++j) ans[j][0] = 1;
  }
  L = 0, R = l;
  for (int i = 1; i < n; ++i) {
    int k = std::get<1>(a[i]) - std::get<1>(a[i + 1]);
    int nl = std::get<3>(a[i]) - std::get<3>(a[i + 1]);
    int nr = nl + std::get<0>(a[i + 1]) - std::get<0>(a[i]);
    assert(nl <= nr);
    if (!k && (nl > 0 || nr < 0)) return void(std::cout << "NO\n");
    if (k > 0)
      L = std::max(L, cei(nl, k)), R = std::min(R, flr(nr, k));
    else if (k < 0)
      L = std::max(L, cei(nr, k)), R = std::min(R, flr(nl, k));
  }
  if (L > R) return void(std::cout << "NO\n");
  for (int i = 1; i < n; ++i) {
    int det = (std::get<3>(a[i + 1]) - L * std::get<1>(a[i + 1])) -
              (std::get<3>(a[i]) - L * std::get<1>(a[i]));
    assert(det >= 0);
    int nl = std::get<0>(a[i]) + 1, nr = std::get<0>(a[i]) + det;
    for (int j = nl; j <= nr; ++j) ans[j][1] = 1;
  }

  for (int i = 1; i <= l; ++i) std::cout << getch(ans[i][0], ans[i][1]);
}

int32_t main() {
#ifdef ORZXKR
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int T = 1;
  // std::cin >> T;
  while (T--) dickdreamer();
  // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
  return 0;
}

标签:std,return,get,int,题解,nr,nl,CF538G,Berserk
From: https://www.cnblogs.com/Scarab/p/18330881

相关文章

  • CF1634F Fibonacci Additions 题解
    CF1634FFibonacciAdditions题解传送门。题目大意:给定两个序列\(A\)和\(B\),每次一个可以选一个区间,并在区间的第\(i\)个数加上\(F_i\),其中\(F\)是斐波那契数列,你需要在每次询问结束时输出两个序列是否相等。可以先求一个序列\(C\)表示\(A\)和\(B\)每个位置的......
  • 剑指Offer题解合集
    剑指Offer题单及题解题目顺序为牛客上剑指Offer专题JZ3、数组中重复的数字分析可以直接对数组进行排序,通过判断首末数字大小来判断数字越界情况,注意数组为空的情况。发现\(0\leqnums[i]\leqn-1\),因此直接开一个数组判断是否有重复数字即可,返回第一个重复数字。代码......
  • 力扣题解2-两数相加
    问题的描述如下:分析过程:为了解决这个问题,我们需要逐位相加两个链表对应位置的值,并处理进位问题。具体步骤如下:初始化一个新的链表,用于存储结果。使用两个指针遍历两个输入链表,逐位相加,同时考虑进位。如果一个链表比另一个短,则将其视为0进行计算。处理最后可能存在的进位......
  • curl发送get和post请求时遇到&截断的问题解决
    get的parameter里带&被截断处理第一种是双引号括住 第二种是加反斜杠转义 post请求的body里有参数的value带了&curl-XPOSThttp://qa-ci.fuxi.netease.com:36800/job/xxxxx/xxxx--userxxxx:xxxxx-d token=popo -d"msg=cd/ssd/deployment_bash&&bashkill.b......
  • P10812 【MX-S2-T3】跳 题解
    题目分析考虑DP。显然当没有\(i\)连向\(i+1\)的边时,整个图是一个DAG,可以直接DP。所以我们DP要解决的唯一问题,就是考虑上\(i\)到\(i+1\)的边。考虑从\(n\)走到\(1\)的过程。当我们从\(i\)向前跳到\(j\)后,此时我们要么向前跳,要么往回走。又因为不能经过重复......
  • CF30E Tricky and Clever Password 题解
    考虑先贪心中间的回文串\(b\),因为这即使影响了两边的字符串,也不会改变最终的总串长。所以先使用manacher跑出来每个位置的最长回文半径。在考虑怎样找出最长的\(a\)和\(a'\)。可以二分答案,设此时答案为\(k\),找出的\(b\)串为\(s[l\dotsr]\),那么其合法的条件就是存在\(......
  • 关于网站安全狗卸载了仍然能拦截的问题解决
    关于网站安全狗卸载了仍然能拦截的问题解决如果你将所有safedog的文件删除的话,可能会导致Apache服务启动不了例如:这里没有提示相关安全狗的信息是因为我已经删除了Apache访问safedog的配置代码,只是提醒错误信息会如上图所示。导致这种原因的结果大概率是因为Apache的conf文件......
  • 题解:P4563 [JXOI2018] 守卫
    思路解法:区间DP。本题虽标上紫题,但黄队说了:“不要被颜色所吓倒。”易得,区间\([l,r]\)中最右端的亭子\(r\)一定会有保镖。先说一下可见性判断吧,只要\(l,r\)的连线的斜率大于\(p,r\)连成的线的斜率大,\(l\)即是可见的。如图,红线是\(r\)无法看到的,而蓝线是\(r\)可......
  • CF1178D Prime Graph 题解
    首先考虑一个问题:如果没有边数是素数的限制,应该怎么构造?这其实很简单,把原图连成一个环即可,每个点度数为\(2\)。接着考虑在原图上加边,注意到\(3\)也是个素数,所以每次可以任意选两个度数为\(2\)的点连边,此时仍然符合条件。这样加边最多可以加\(\left\lfloor\frac{n}{2}\rig......
  • CF685E 题解
    吐槽一下,为啥这道题\(\mathcal{O}(nm)\)可以过。联考的时候做到了这道题,还一直在想更快的算法。。。然后,这联考的数据是自己出的,有\(s=t\)的情况,我反正是完全没有想到,又因为是捆绑测试,直接痛失\(100pts\)。首先考虑转化一下题目。对于一个询问\(l,r,s,t\),就相当于是让你......