0%

杭电 OJ 暂不支持调整栈空间大小。如果使用 G++ 提交代码,并且代码中含有递归,递归层数较深,会返回 Runtime Error (STACK_OVERFLOW)。添加如下代码可以开大栈空间:

1
2
3
4
5
6
7
int main() {
int size(256<<20); // 256M
__asm__ ( "movq %0, %%rsp\n"::"r"((char*)malloc(size)+size));
// 关同步流代码
// 主程序代码
exit(0); // 一定要添加这一条,不然会返回 Runtime Error (ACCESS_VIOLATION)
}

题目大意

题目描述

给定二维平面第一象限上的 nn 个弹幕发射器。第 ii 个发射器位于坐标 (xi,yi)(x_i, y_i),并向四个方向之一发射一条射线(激光):

  • di=0d_i = 0:向上发射

  • di=1d_i = 1:向右发射

  • di=2d_i = 2:向下发射

  • di=3d_i = 3:向左发射

射线的照明路径包含发射器本身所在的位置。题目保证任意两个发射器不会同时在对方的照明路径上。

现在可以在平面上放置障碍物(允许放置在发射器所在的坐标上),只要障碍物位于某条射线上,就能阻挡该射线的照射。求最少需要放置多少个障碍物,才能使得所有 nn 个发射器的照射路径上都至少包含一个障碍物。

输入格式

第一行包含一个整数 tt1t1001 \le t \le 100),表示测试用例的数量。

每个测试用例第一行包含一个整数 nn1n3001 \le n \le 300),表示发射器的数量。
接下来 nn 行,每行包含三个整数 xi,yi,dix_i, y_i, d_i1xi,yi1091 \le x_i, y_i \le 10^9di{0,1,2,3}d_i \in \{0, 1, 2, 3\}),表示发射器的坐标与发射方向。

保证所有测试用例中 nn 的总和不超过 30003000

输出格式

对于每个测试用例,输出一行一个整数,表示最少需要放置的障碍物数量。

样例输入

1
2
3
4
5
6
7
8
9
10
2
6
5 5 0
3 7 1
9 9 2
9 1 3
5 2 0
1 20 3
1
1 1 0

样例输出

1
2
3
1

样例解释

在第一个测试用例中,有 66 个发射器。一种最优方案是放置 33 个障碍物,具体位置如下:

  1. 在坐标 (5,7)(5, 7) 处放置一个障碍物:该点覆盖了第 11 束(从 (5,5)(5,5) 向上)、第 22 束(从 (3,7)(3,7) 向右)以及第 55 束(从 (5,2)(5,2) 向上)激光。

  2. 在坐标 (9,1)(9, 1) 处放置一个障碍物:该点覆盖了第 33 束(从 (9,9)(9,9) 向下)以及第 44 束(从 (9,1)(9,1) 向左)激光。

  3. 在坐标 (2025,20)(-2025, 20) 处放置一个障碍物:该点覆盖了第 66 束(从 (1,20)(1,20) 向左)激光。

该方案共使用了 33 个障碍物,且可以证明不存在比 33 更少的放置方案。

思路讲解

一种错误的图论建模方式是把激光当作左边的点,把这个障碍物当成右边的点,但是这样子建图是做不出来这道题目的,因为我们不是要让激光和障碍物一一匹配,这个非常容易就能做到。

P3386 【模板】二分图最大匹配

那么要做这道题目,最重要的就是我们要把障碍物看成连边,左边的点指的是这个方向为上下的点,右边的点指的是这个方向为左右的点

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void Solve() {
ll N;
cin >> N;
vector<X_y_d> xyd_ls(N);
for (int i = 0; i < N; ++i) {
cin >> xyd_ls[i].x >> xyd_ls[i].y >> xyd_ls[i].d;
}
xyd_ls = unique_xyd_ls(xyd_ls);
auto g = build_graph(xyd_ls);
Bi_graph_matcher matcher(g,SZ(xyd_ls));
ll mx_match = matcher.mx_match();
ll ans = (SZ(xyd_ls) - 2 * mx_match) + mx_match;
cout << ans << "\n";
}

AC代码

AC
https://acm.hdu.edu.cn/contest/view-code?cid=1198&rid=18859

心路历程(WA,TLE,MLE……)

最好显式忽略这个其他情况:

image

使用 offset 进行 swap,最后也要 swap 回来。

image

将哨兵值设置为 -1,可以避免 0-based 造成问题。

image

题目大意

题目描述

给定一个数组 aa,定义 f(a)f(a) 为将 aa 划分成一个或多个连续子数组的方案数,需满足以下条件:

  1. 每个元素恰好属于一个子数组。

  2. 所有子数组的元素和都相等。

例如,对于 a=[1,1]a=[1,1]f(a)=2f(a)=2,因为有两种合法的划分方案:

  • [1,1][1,1],此时唯一的子数组和为 22

  • [1]+[1][1]+[1],此时两个子数组和均为 11

给定两个整数 xxyy。你需要构造一个长度为 x+yx+y 的数组 aa,其中包含 xx11yy1-1
你需要求出在所有合法的数组 aa 中,f(a)f(a)最小值,并将该最小值对 676767677676767677 取模后输出。同时,你需要输出一个能达到该最小值的数组构造方案。

注意:你需要最小化的是 f(a)f(a) 本身,然后将这个最小值对 676767677676767677 取模,而不是去最小化 f(a)mod676767677f(a) \bmod 676767677 的结果。

输入格式

第一行包含一个整数 tt (1t1041 \le t \le 10^4),表示测试用例的数量。

接下来每个测试用例包含一行,包含两个整数 xxyy (0x,y21050 \le x, y \le 2 \cdot 10^5),保证 x+y1x+y \ge 1

保证所有测试用例中 xx 的总和与 yy 的总和均不超过 21052 \cdot 10^5

输出格式

对于每个测试用例,输出两行:
第一行输出 f(a)f(a) 的最小值对 676767677676767677 取模的结果。
第二行输出一个达到该最小值的数组 aa 的元素(用空格分隔)。

样例输入

1
2
3
4
5
4
2 0
1 1
6 7
1 3

样例输出

1
2
3
4
5
6
7
8
2
1 1
1
1 -1
1
-1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1
2
-1 -1 -1 1

样例解释

在第一个测试用例中,x=2x=2y=0y=0。唯一可能的数组是 a=[1,1]a=[1,1],正如题目描述中所解释的,此时 f(a)=2f(a)=2

在第二个测试用例中,x=1x=1y=1y=1。一个能使 f(a)f(a) 最小化的合法数组是 a=[1,1]a=[1,-1]。此时 f(a)=1f(a)=1,因为唯一能使所有子数组和相等的划分方式就是不进行任何分割(即 [[1,1]][[1,-1]],子数组和为 00)。

思路讲解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void Solve() {
ll X, Y;
cin >> X >> Y;
vector<ll> A(X + Y + 2);
for (int i = 1; i <= X; ++i) {
// cout << 1 << " ";
A[i] = 1;
}
for (int i = 1; i <= Y; ++i) {
// cout << -1 << " ";
A[i + X] = -1;
}
ll s = llabs(X - Y);
ll ans = 1;
// 这里要采用求约数个数的方法
if (s != 0) {
ans = 0;
for (ll d = 1; d * d <= s; ++d) {
if (s % d == 0) {
++ans;
if (d * d != s) ++ans;
}
}
}
cout << ans << "\n";
for (int i = 1; i <= X + Y; ++i) {
cout << A[i] << " ";
}
cout << "\n";
// mod
}

AC代码

AC

https://codeforces.com/contest/2211/submission/368623804

心路历程(WA,TLE,MLE……)

题目大意

题目描述
给定一个长度为 nn 的数组 aa 和一个参数 kk。如果一个数组 bb 满足以下条件,则称其为“很酷的”:
对于从 kknn 的每个下标 ii,子数组 [aik+1,aik+2,,ai][a_{i-k+1}, a_{i-k+2}, \dots, a_i] 都是子数组 [bik+1,bik+2,,bi][b_{i-k+1}, b_{i-k+2}, \dots, b_i] 的重新排列(即两个长度为 kk 的滑动窗口构成的多重集相同)。

现在给定数组 aa 和数组 bb。数组 aa 仅包含 11nn 之间的整数;数组 bb 包含 11nn 之间的整数以及 1-1
请判断是否可以通过将 bb 中所有的 1-1 替换为 11nn 之间的任意整数,使得最终的数组 bb 满足上述“很酷的”条件。

输入格式
第一行包含一个整数 tt1t1041 \le t \le 10^4),表示测试用例的数量。
每个测试用例的第一行包含两个整数 nnkk1kn21051 \le k \le n \le 2 \cdot 10^5)。
第二行包含 nn 个整数 a1,a2,,ana_1, a_2, \dots, a_n1ain1 \le a_i \le n)。
第三行包含 nn 个整数 b1,b2,,bnb_1, b_2, \dots, b_n1bin1 \le b_i \le nbi=1b_i = -1)。
保证所有测试用例中 nn 的总和不超过 21052 \cdot 10^5

输出格式
对于每个测试用例,如果可以构造出满足条件的数组 bb,输出 YES,否则输出 NO

样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Input
5
5 5
1 2 3 4 5
3 1 5 2 4
5 2
1 2 1 2 1
2 -1 -1 -1 -1
6 1
5 6 2 2 4 3
5 -1 -1 2 -1 3
2 1
1 2
2 -1
6 4
1 2 3 4 1 2
2 -1 3 -1 4 -1

Output
YES
YES
YES
NO
NO

样例解释第一个测试用例k=5k=5。唯一的长度为 55 的子数组是整个数组本身。给定的 bb 已经是 aa 的一个重新排列,且没有 1-1,满足条件,答案为 YES
第二个测试用例k=2k=2。我们可以将所有的 1-1 替换,使得 b=[2,1,2,1,2]b = [2, 1, 2, 1, 2]。此时在 aabb 中,每一个长度为 22 的窗口要么是 [1,2][1, 2] 要么是 [2,1][2, 1],它们互为重新排列,因此答案为 YES
第四个测试用例k=1k=1。长度为 11 的窗口意味着对应位置的元素必须完全相同。因为已知 a1=1a_1 = 1b1=2b_1 = 2,两者不相等,所以无法满足条件,答案为 NO

思路讲解

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
void Solve() {
ll N, K;
cin >> N >> K;
vector<ll> A(N + 1), B(N + 1);
for (int i = 1; i <= N; ++i) cin >> A[i];
for (int i = 1; i <= N; ++i) cin >> B[i];

// target: 第一个窗口 a[1..K] 的多重集,b[1..K] 也必须是它的一个排列
map<ll, ll> target;
for (int i = 1; i <= K; ++i) target[A[i]]++;

// free_count: 第一个窗口中,值完全自由(可任意选取)的位置数
int free_count = 0;

// 按模 K 将位置分成 K 条链:链 r 包含位置 r, r+K, r+2K, ...
// 每条链恰好有一个位置落在第一个窗口(即位置 r 本身)
//
// 关键推导:窗口从 [i, i+K-1] 滑到 [i+1, i+K] 时,
// 需要 -{b_i} + {b_{i+K}} = -{a_i} + {a_{i+K}}
// 因此:
// - 若 a_i ≠ a_{i+K}:必须 b_i = a_i 且 b_{i+K} = a_{i+K}
// - 若 a_i = a_{i+K}:只需 b_i = b_{i+K}(不一定等于 a)
//
// 对一条链来说:
// - 若链中存在相邻位置 a 值不同("固定链"),则整条链的 b 值全部被唯一确定为 a 值
// - 若链中所有 a 值全相同("自由链"),则链上所有 b 值必须相等,但具体取什么值是灵活的

for (int r = 1; r <= K; ++r) {
// 检查链 r 是否所有 a 值都相同
bool all_equal = true;
for (int p = r; p + K <= N; p += K) {
if (A[p] != A[p + K]) { all_equal = false; break; }
}

if (!all_equal) {
// 固定链:链上每个位置 b[p] 必须等于 a[p]
// 检查已给定的 b 值是否与 a 一致
for (int p = r; p <= N; p += K) {
if (B[p] != -1 && B[p] != A[p]) {
cout << "NO\n"; return;
}
}
// 位置 r(第一个窗口中的位置)的 b 值确定为 a[r],从 target 中扣除
target[A[r]]--;
} else {
// 自由链:链上所有 b 值必须相等
// 检查所有已给定的 b 值是否互相一致
ll forced = -1;
for (int p = r; p <= N; p += K) {
if (B[p] != -1) {
if (forced == -1) forced = B[p]; // 第一个给定值,记录
else if (forced != B[p]) { // 与之前的给定值矛盾
cout << "NO\n"; return;
}
}
}
if (forced != -1) target[forced]--; // 链的值已确定,从 target 扣除
else free_count++; // 链的值完全自由,待分配
}
}

// 最终检查:target 中剩余的值(还没被匹配的)必须恰好分配给 free_count 个自由位置
// 且不能有任何值被"过度消耗"(计数变负)
ll remaining = 0;
for (auto& [v, cnt] : target) {
if (cnt < 0) { cout << "NO\n"; return; }
remaining += cnt;
}
// 剩余的值刚好够填满所有自由位置 → YES,否则 → NO
cout << (remaining == free_count ? "YES" : "NO") << "\n";
}

AC代码

心路历程(WA,TLE,MLE……)

题目大意

题目描述

对于一个长度为 nn 的未知序列 aa,定义其 AND-数组 f(a)f(a) 如下:

f(a)k=1i1<i2<<iknai1&ai2&&aikf(a)k = \sum{1 \le i_1 < i_2 < \dots < i_k \le n} a_{i_1} \mathbin{\&} a_{i_2} \mathbin{\&} \dots \mathbin{\&} a_{i_k}

其中 1kn1 \le k \le n&\mathbin{\&} 表示按位与操作。换句话说,f(a)kf(a)_k 是序列 aa 中所有长度为 kk 的子序列的按位与结果之和。

现在给定一个长度为 nn 的序列 bb,满足对于所有的 1in1 \le i \le n,都有 bif(a)i(mod109+7)b_i \equiv f(a)_i \pmod{10^9+7}

请根据给定的序列 bb,构造并输出任意一个满足条件的序列 aa

输入格式

第一行包含一个整数 tt1t1041 \le t \le 10^4),表示测试用例的数量。

每个测试用例包含两行:
第一行包含一个整数 nn1n1051 \le n \le 10^5),表示序列 aabb 的长度。
第二行包含 nn 个整数 b1,b2,,bnb_1, b_2, \dots, b_n0bi<109+70 \le b_i < 10^9+7),表示序列 bb

保证存在长度为 nn 且满足 0ai<2290 \le a_i < 2^{29} 的序列 aa 使得条件成立。
保证所有测试用例中 nn 的总和不超过 10510^5

输出格式

对于每个测试用例,输出 nn 个整数 a1,a2,,ana_1, a_2, \dots, a_n0ai<2290 \le a_i < 2^{29}),表示重构出的序列 aa。如果有多个满足条件的序列,输出任意一个即可。

样例输入

1
2
3
4
5
6
7
3
3
0 0 0
5
22 24 10 1 0
10
130 585 1560 2730 3276 2730 1560 585 130 13

样例输出

1
2
3
0 0 0
5 3 6 1 7
13 13 13 13 13 13 13 13 13 13

样例解释

在第二个样例中,若构造的序列 a=[5,3,6,1,7]a = [5, 3, 6, 1, 7],其 f(a)4f(a)_4 的值为:
(a1&a2&a3&a4)+(a1&a2&a3&a5)+(a1&a2&a4&a5)+(a1&a3&a4&a5)+(a2&a3&a4&a5)=0+0+1+0+0=1(a_1 \mathbin{\&} a_2 \mathbin{\&} a_3 \mathbin{\&} a_4) + (a_1 \mathbin{\&} a_2 \mathbin{\&} a_3 \mathbin{\&} a_5) + (a_1 \mathbin{\&} a_2 \mathbin{\&} a_4 \mathbin{\&} a_5) + (a_1 \mathbin{\&} a_3 \mathbin{\&} a_4 \mathbin{\&} a_5) + (a_2 \mathbin{\&} a_3 \mathbin{\&} a_4 \mathbin{\&} a_5) = 0 + 0 + 1 + 0 + 0 = 1
f(a)1=a1+a2+a3+a4+a5=22f(a)_1 = a_1 + a_2 + a_3 + a_4 + a_5 = 22。可以证明对于所有 1i51 \le i \le 5 均有 f(a)i=bif(a)_i = b_i,因此 a=[5,3,6,1,7]a = [5, 3, 6, 1, 7] 是一个合法的解。

思路讲解

AC代码

心路历程(WA,TLE,MLE……)