D
在一个N*N的平面中有一些墙,还放置了两个棋子
每次操作只能将两个棋子同时上下左右移动,如果棋子被墙挡住就不能动
问最少需要几步能将两个棋子走到一起
bfs
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
int n;
char s[70][70];
struct Item {
int r0, c0, r1, c1;
};
int f[61][61][61][61];
int dir[4][2] = {
{0, 1}, {-1, 0}, {0, -1}, {1, 0}
};
int main(){
//freopen("in.txt", "r", stdin);
cin >> n;
for (int i = 0; i < 70; ++i) {
for (int j = 0; j < 70; ++j) {
s[i][j] = '#';
}
}
vector<pii> temp;
for (int i = 1; i <= n; ++i) {
string t;
cin >> t;
for (int j = 1; j <= n; ++j) {
s[i][j] = t[j - 1];
if (s[i][j] == 'P') {
temp.push_back({ i, j });
}
}
}
memset(f, 0x3f, sizeof(f));
queue<Item> qu;
auto [r0, c0] = temp[0];
auto [r1, c1] = temp[1];
if (r0 > r1) {
swap(r0, r1);
swap(c0, c1);
}
qu.push(Item{ r0, c0, r1, c1 });
f[r0][c0][r1][c1] = 0;
int ans = -1;
while (qu.size()) {
auto [r0, c0, r1, c1] = qu.front();
qu.pop();
if (r0 == r1 && c0 == c1) {
ans = f[r0][c0][r1][c1];
break;
}
for (auto d : dir) {
int nr0 = r0 + d[0], nc0 = c0 + d[1];
int nr1 = r1 + d[0], nc1 = c1 + d[1];
if (s[nr0][nc0] == '#') {
nr0 = r0, nc0 = c0;
}
if (s[nr1][nc1] == '#') {
nr1 = r1, nc1 = c1;
}
if (nr0 > nr1) {
swap(nr0, nr1);
swap(nc0, nc1);
}
int val = f[r0][c0][r1][c1] + 1;
if (f[nr0][nc0][nr1][nc1] > val) {
f[nr0][nc0][nr1][nc1] = val;
qu.push(Item({ nr0, nc0, nr1, nc1 }));
}
}
}
printf("%d\n", ans);
return 0;
}
E
给定一个数列
A
A
A
获取长度最长的子序列,其中相邻两项的差绝对值不得大于d
这个题有
A
i
<
=
500000
A_i<=500000
Ai<=500000的限制,所以好做一点,直接上线段树
对于每个
A
i
A_i
Ai,求
A
i
−
d
A_i-d
Ai−d到
A
i
+
d
A_i+d
Ai+d范围内的最大答案再加1
如果没有数据限制,问题规模也不是特别大,把
A
i
,
A
i
−
d
,
A
i
+
d
A_i,A_i-d,A_i+d
Ai,Ai−d,Ai+d这些点离散化就可以了。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
#define lu (u * 2)
#define ru (u * 2 + 1)
const int N = 500005;
int a[N];
int f[N];
int n, d;
struct SegTree {
struct Node {
int l, r, mx;
} tr[N << 2];
void up(int u) {
tr[u].mx = max(tr[lu].mx, tr[ru].mx);
}
public:
void build(int l, int r, int u) {
tr[u] = { l, r, 0 };
if (l == r)
return;
int mi = (l + r) / 2;
build(l, mi, lu);
build(mi + 1, r, ru);
}
void update(int pos, int u, int val) {
if (tr[u].l == tr[u].r) {
tr[u].mx = val;
return;
}
int mi = (tr[u].l + tr[u].r) / 2;
if (pos <= mi)
update(pos, lu, val);
else
update(pos, ru, val);
up(u);
}
int query(int l, int r, int u) {
if (l <= tr[u].l && tr[u].r <= r) {
return tr[u].mx;
}
int mi = (tr[u].l + tr[u].r) / 2;
int rt = 0;
if (l <= mi) {
rt = max(rt, query(l, r, lu));
}
if (r > mi) {
rt = max(rt, query(l, r, ru));
}
return rt;
}
} st;
int main(){
//freopen("in.txt", "r", stdin);
cin >> n >> d;
st.build(1, 500000, 1);
int ans = 0;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
int l = max(1, a[i] - d), r = min(500000, a[i] + d);
f[i] = st.query(l, r, 1) + 1;
st.update(a[i], 1, f[i]);
ans = max(ans, f[i]);
}
printf("%d\n", ans);
return 0;
}
F
N个超级大数
A
i
<
1
0
1000
A_i<10^{1000}
Ai<101000
求
A
i
∗
A
k
=
A
j
A_i*A_k=A_j
Ai∗Ak=Aj的tuple数
随机化题,思路是bloom filter的方法,知道这个方法就不难
如果两个大质数还是wa,那就再来一个filter
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
int n;
ll a[1001], b[1001];
ll p0 = 10000019;
ll p1 = 99999989;
map<pll, int> h;
int main() {
//freopen("in.txt", "r", stdin);
cin >> n;
for (int i = 1; i <= n; ++i) {
string s;
cin >> s;
int m = s.length();
ll t = 0;
for (int j = 0; j < m; ++j) {
t = t * 10 + s[j] - '0';
t %= p0;
}
a[i] = t;
t = 0;
for (int j = 0; j < m; ++j) {
t = t * 10 + s[j] - '0';
t %= p1;
}
b[i] = t;
h[{a[i], b[i]}] ++;
}
int ans = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
ll v0 = a[i] * a[j] % p0, v1 = b[i] * b[j] % p1;
if (h.count({ v0, v1 })) {
ans += h[{v0, v1}];
}
}
}
printf("%d\n", ans);
return 0;
}