老夫聊发少年狂,碱金属,丢池塘。浮溶游响,激起千朵|

Yaosicheng124

园龄:1年2个月粉丝:8关注:11

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

B. 广告效应

题目描述

N 户人家在一个数轴上,第 i 户人在 xi,影响力为 pi。你决定把你的书送给一些人并让他们推销。如果一对人 i,j 满足:你送了 i 书且 |xixj|pipj,那么 j 会买你的书。

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

思路

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

空间复杂度 O(N),时间复杂度 O(NlogN)

代码

#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×M 的迷宫,其中有空地和墙壁。你可以在空地中上下左右移动,但是你不一定能直接到达终点。你有一种法术,可以使任意 K×K 的矩形中的墙壁消失。求到达终点至少需要使用几次法术。

思路

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

空间复杂度 O(NM),时间复杂度 O(NMlogNM)

代码

#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;
}

本文作者:yaosicheng124

本文链接:https://www.cnblogs.com/yaosicheng124/p/18473284

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Yaosicheng124  阅读(4)  评论(0编辑  收藏  举报
  1. 1 Minecraft C418
Minecraft - C418
00:00 / 00:00
An audio error has occurred.

暂无歌词

加载中…

{{tag.name}}

{{tran.text}}{{tran.sub}}
无对应文字
有可能是
{{input}}
尚未录入,我来提交对应文字
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示