菜鸡的$div2$补题现场……
A:Little Artem 1.题目描述:
给你一个$n * m$的矩形,现在让你涂色。$’B’$表示黑色,$’W’$表示白色。
Lets $B$ be the number of black cells that have at least one white neighbor adjacent by the side. Let $W$ be the number of white cells that have at least one black neighbor adjacent by the side.
先(重新)定义:
$’B’$表示具有至少一个相邻的白色邻居的单元格数量。
$‘W’$表示具有至少一个相邻的黑色邻居的单元格数量。
当$B = W + 1$时,我们称该矩形是好的。
让你输出任何一个好的矩形。
input:
output:
2.思路
【!!!读题仔细!!!】
所以我们可以构造出一个样例,即构造出$2 (B)= 1(W) + 1$这种,就满足题目要求。
我们就可以让随便一个位置为$W$,然后构造两个$B$围着即可。
即矩形四个角的位置设置为$W$,其他均为$B$即可。
【qwq 我没有想到www~】
3.代码:
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 #include <bits/stdc++.h> #define IOS {ios::sync_with_stdio(false);cin.tie(0);} #define ll long long #define INF 0x3f3f3f3f using namespace std ;int t, n, m;int main () { IOS cin >> t; while (t--) { cin >> n >> m; for (int i = 1 ; i <= n; i++) { for (int j = 1 ; j <= m; j++) { if (i == 1 && j == m) { cout <<'W' ; } else { cout <<'B' ; } } cout << endl ; } } return 0 ; }
B:Kind Anton 1.题目描述
一个$a$数组,里边的元素只有${-1, 0, 1}$,你可以执行操作:
选择一对$(i, j)$满足$1 \le i < j \le n$,可以多次选择同一对。
将$a_i$ 加到$a_j$上, 即:$a_j = a_i + a_j$
问:给你一个$a$, $b$,能否对$a$进行上述操作,使得成为$b$数组?输出”YES/NO”
数据量:
T组数据:$1\le t \le 10000$
N—数组长度:$1\le n \le 10^5$
input: .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 5 3 1 -1 0 1 1 -2 3 0 1 1 0 2 2 2 1 0 1 41 2 -1 0 -1 -41 5 0 1 -1 1 -1 1 1 -1 1 -1
output:
2.思路:
思维题
我们考虑,既然$i < j$恒成立,则:当$a_j <= a_j$时,我们就可以通过无限次累加$1$使得成立。
即:当$a_j >= a_j$时,我们也可以通过无限次累加$-1$使得成立。
所以我们要做的判断就是当$a_j <= b_j$时,是否存在$1$使得可以成立。 $>=$情况同理。
具体细节见代码。
逻辑判断条件要搞清….不然会很乱….
3.代码:
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 #include <bits/stdc++.h> #define IOS {ios::sync_with_stdio(false);cin.tie(0);} #define ll long long #define INF 0x3f3f3f3f using namespace std ;int t, n, x;const int maxn = 1e5 + 5 ;int a[maxn], b[maxn];bool solve () { bool flag = false , x1 = false , x2 = false ; for (int i = 1 ; i <= n; i++) { if (a[i] < b[i] && !x1) { flag = true ; break ; } else if (a[i] > b[i] && !x2) { flag = true ; break ; } if (a[i] == 1 ) { x1 = true ; } else if (a[i] == -1 ) { x2 = true ; } } return flag; } int main () { IOS cin >> t; while (t--) { memset (a, 0 , sizeof (a)); memset (b, 0 , sizeof (b)); cin >> n; for (int i = 1 ; i <= n; i++) { cin >> a[i]; } for (int i = 1 ; i <= n; i++) { cin >> b[i]; } if (solve()) { puts ("NO" ); } else { puts ("YES" ); } } system("pause" ); return 0 ; }
C:Eugene and an array 1.题目描述
给你一个序列$a$,让你找出$a$的所有$sum != 0$的子序列个数。
input:
1 2 3 4 5 6 first: 3 1 2 -3 second: 3 41 -41 41
output:
2.思路:
子序列$sum$问题考虑前缀和。
题目中说明:一个序列的子序列如果$sum == 0$那么也不是一个$good$序列。于是我们可以用一个$map$来维护当前的前缀和,即:维护$sum$和对应的下标$i$。
!!!注意!!求前缀和的时候,原来的每一项数据范围是$int$,可能会爆$int$,所以我们采用$long long map$来维护。
【就是$map$保存前缀和嘛~出现前缀和相同,就是证明里边有$sum == 0$的子串,我们就去找最大左端点,然后用当前减去即可。】
思路就是 :
我们首先对每一个i 找包含$a[i]$的子串的个数
显然为$n$个,证明:对于第$i$个,左边有$i - 1$个,右边有$n - i$个,包含自身,即:$i - 1 + 1 + n - i$ 为$n$
我们可以枚举每一个$a[i]$,求出其往左延伸有多少符合的子串,然后我们在加一下即可。
对每一个$a[i]$,我们最后$ans += i - (max_l + 1)$[注意要+1,$max_l$ 表示前缀和相等的下标,实际区间要多减去1]
3.代码:
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 #include <bits/stdc++.h> #define IOS {ios::sync_with_stdio(false);cin.tie(0);} #define ll long long #define INF 0x3f3f3f3f #define endl "\n" using namespace std ;const int maxn = 2e5 + 5 ;ll a[maxn]; ll ans; map <ll, ll>mp;int main () { IOS int n; cin >> n; for (int i = 1 ; i <= n; i++) { cin >> a[i]; } ll sum = 0 ; mp[0 ] = 0 ; ll temp = -1 ; for (int i = 1 ; i <= n; i++) { sum += a[i]; if (mp.count(sum)) { temp = max (temp, mp[sum]); } mp[sum] = i; ans += i - (temp + 1 ); } cout << ans << endl ; system("pause" ); return 0 ; }