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;
}
标签:Node,38,dist,int,2024,pq,MAXN,const,初秋
From: https://www.cnblogs.com/yaosicheng124/p/18473284