2024初秋集训——提高组 #38

B. 广告效应

题目描述

\(N\) 户人家在一个数轴上,第 \(i\) 户人在 \(x_i\),影响力为 \(p_i\)。你决定把你的书送给一些人并让他们推销。如果一对人 \(i,j\) 满足:你送了 \(i\) 书且 \(|x_i-x_j|\le p_i-p_j\),那么 \(j\) 会买你的书。

求你至少要送几个人书才能让所有人都有你的书。

思路

这个东西很明显有传递性,即 \(i\rightarrow j,j\rightarrow k\),那么一定有 \(i\rightarrow k\)。所以我们一定只会选择哪些无法被别人送书的人,只需排序,并记录最大/小值即可。

空间复杂度 \(O(N)\),时间复杂度 \(O(N\log N)\)

代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 500001;

struct Node {
  int x, p, id;
}s[MAXN];

int n, ans, tot;
bool vis[MAXN];

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n;
  for(int i = 1; i <= n; ++i) {
    cin >> s[i].x >> s[i].p;
    s[i].id = i;
  }
  sort(s + 1, s + n + 1, [](const Node &a, const Node &b) -> bool {
    return a.x < b.x || (a.x == b.x && a.p > b.p);
  });
  for(int i = 1; i <= n; ++i) {
    if(s[i].x != s[tot].x || s[i].p != s[tot].p) {
      s[++tot] = s[i];
    }
  }
  for(int i = 1, Max = 0; i <= tot; ++i) {
    if(Max >= s[i].x + s[i].p) {
      vis[i] = 1;
    }
    Max = max(Max, s[i].x + s[i].p);
  }
  for(int i = tot, Min = int(2e9) + 1; i >= 1; --i) {
    if(Min <= s[i].x - s[i].p) {
      vis[i] = 1;
    }
    Min = min(Min, s[i].x - s[i].p);
  }
  for(int i = 1; i <= tot; ++i) {
    ans += !vis[i];
  }
  cout << ans;
  return 0;
}

C. 易形迷宫

题目描述

有一个 \(N\times M\) 的迷宫,其中有空地和墙壁。你可以在空地中上下左右移动,但是你不一定能直接到达终点。你有一种法术,可以使任意 \(K\times K\) 的矩形中的墙壁消失。求到达终点至少需要使用几次法术。

思路

显然法术只会紧贴着自己的位置使用,并且不会多次经过法术的区域,所以我们可以把它看作临时的。一个法术可以让你接下来 \(k-1\) 步无视墙壁(这里也可以斜着走),我们记录使用了几次法术,当前的法术还剩下多少步。这样跑最短路即可。

空间复杂度 \(O(NM)\),时间复杂度 \(O(NM\log NM)\)

代码

#include<bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;

const int MAXN = 2505, dx[] = {-1, 1, 0, 0, -1, -1, 1, 1}, dy[] = {0, 0, -1, 1, -1, 1, -1, 1}, INF = int(1e9);

struct Node {
  int x, y, d, c;
};

struct cmp {
  bool operator()(const Node &a, const Node &b) const {
    return a.d > b.d || (a.d == b.d && a.c < b.c);
  }
};

int n, m, k, sx, sy, tx, ty;
vector<char> ch[MAXN];
vector<bool> vis[MAXN];
vector<pii> dist[MAXN];
priority_queue<Node, vector<Node>, cmp> pq;

void C(int x, int y, int d, int c) {
  if(x < 1 || x > n || y < 1 || y > m) {
    return;
  }
  c = 0;
  if(ch[x][y] == '#') {
    d++, c = k - 1;
  }
  if(d < dist[x][y].first || (d == dist[x][y].first && c > dist[x][y].second)) {
    dist[x][y] = {d, c};
    pq.push({x, y, d, c});
  }
}

void F(int x, int y, int d, int c) {
  if(x < 1 || x > n || y < 1 || y > m) {
    return;
  }
  c--;
  if(d < dist[x][y].first || (d == dist[x][y].first && c > dist[x][y].second)) {
    dist[x][y] = {d, c};
    pq.push({x, y, d, c});
  }
}

void dij() {
  pq.push({sx, sy, 0, 0}), dist[sx][sy] = {0, 0};
  for(; !pq.empty(); ) {
    auto [x, y, d, c] = pq.top();
    pq.pop();
    //cout << x << " " << y << " " << d << " " << c << "\n";
    if(vis[x][y]) {
      continue;
    }
    vis[x][y] = 1;
    for(int i : {0, 1, 2, 3}) {
      C(x + dx[i], y + dy[i], d, c);
    }
    if(!c) {
      continue;
    }
    for(int i : {0, 1, 2, 3, 4, 5, 6, 7}) {
      F(x + dx[i], y + dy[i], d, c);
    }
  }
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n >> m >> k >> sx >> sy >> tx >> ty;
  for(int i = 1; i <= n; ++i) {
    ch[i].resize(m + 1), vis[i].resize(m + 1), dist[i].resize(m + 1);
    for(int j = 1; j <= m; ++j) {
      cin >> ch[i][j];
      dist[i][j] = {INF, -1};
    }
  }
  dij();
  cout << dist[tx][ty].first;
  return 0;
}
posted @ 2024-10-17 23:02  Yaosicheng124  阅读(1)  评论(0编辑  收藏  举报