题目链接:Dashboard - Codeforces Round 877 (Div. 2) - Codeforces
A - Blackboard List
解题思路:因为取的是绝对值,所以有负数肯定取负数,没负数就取最大值。
#include <bits/stdc++.h>
using namespace std;
const int mx = 1e2 + 10;
int a[mx];
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
for (int i=1;i<=n;i++) {
scanf("%d", a+i);
}
sort(a + 1, a + 1 + n);
if (a[1] < 0) {
printf("%d\n", a[1]);
} else {
printf("%d\n", a[n]);
}
}
return 0;
}
B - Minimize Permutation Subarrays
解题思路:我们只需要考虑3个数,1、2、n。他们的位置关系应该是1...n...2或者2...n...1,那么就可以让数组的值永远是2。交换的话其实只需要考虑1和n位置的边界和本身就行了。
#include <bits/stdc++.h>
using namespace std;
const int mx = 2e5 + 10;
int a[mx];
int find_pos(int n, int p) {
for (int i=1;i<=n;i++) {
if (a[i] == p)
return i;
}
return -1;
};
int main() {
auto check = [](int n, int x, int y) {
if (x < 1 || x > n || y < 1 || y > n)
return (int)1e9;
swap(a[x], a[y]);
int find_1 = find_pos(n, 1);
//cout << x << " " << y << " " << find_1 << endl;
int ma = 1, p = find_1;
int l = p - 1, r = p + 1;
int ans = 1;
while (l != 0 || r != n + 1) {
if (r - l - 1 == ma) {
ans++;
}
if (a[l] < a[r]) {
ma = max(ma, a[l]);
l--;
} else {
ma = max(ma, a[r]);
r++;
}
}
swap(a[x], a[y]);
return ans;
};
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
for (int i=1;i<=n;i++) {
scanf("%d", a+i);
}
a[0] = a[n+1] = 1e9;
int find_1 = find_pos(n, 1);
int find_n = find_pos(n, n);
int ans = 1e9;
int x, y;
auto change_ans = [&](int p1, int p2){
int temp = check(n, p1, p2);
//cout << temp << " ### " << endl;
if (temp < ans) {
ans = temp;
x = p1, y = p2;
}
};
change_ans(find_1, find_n-1);
change_ans(find_1, find_n+1);
change_ans(find_1-1, find_n);
change_ans(find_1+1, find_n);
change_ans(find_1, find_n);
printf("%d %d\n", x, y);
}
return 0;
}
C - No Prime Differences
解题思路:其实问题是存在素数的问题,如果n和m都是合数,那么直接按照顺序1,2,3,4,,,n这样左右两边差都是1,上下两边差就是m了。但是如果m是质数的话就无法满足条件,所以我们需要调换顺序,首先分1,2,3,,,,m;m+1,m+2,,,,,2*m;....;(n-1)*m+1,(n-1)*m+2,,,,n*m。然后以1,3,5,7,n,2,4,6,8....这样就保证了左右差是1,上下差是x*m,就解决了。
#include <bits/stdc++.h>
using namespace std;
const int mx = 1e3 + 10;
int a[mx][mx];
int main() {
auto check = [](int x){
for (int i=2;i*i<=x;i++) {
if (x % i == 0)
return false;
}
return true;
};
int t;
scanf("%d", &t);
while (t--) {
int m, n;
scanf("%d%d", &n, &m);
int flag = 1;
if (n < m)
swap(n,m), flag = 0;
for (int i=1;i<=n;i+=2) {
for (int j=1;j<=m;j++) {
a[i/2+1][j] = (i-1)*m + j;
}
}
for (int i=2;i<=n;i+=2) {
for (int j=1;j<=m;j++) {
a[i/2+(n-1)/2+1][j] = (i-1)*m + j;
}
}
if (flag) {
for (int i=1;i<=n;i++) {
for (int j=1;j<=m;j++) {
printf("%d ", a[i][j]);
}
puts("");
}
} else {
for (int i=1;i<=m;i++) {
for (int j=1;j<=n;j++) {
printf("%d ", a[j][i]);
}
puts("");
}
}
}
return 0;
}
D - Bracket Walk
解题思路:首先当n为奇数的时候答案肯定无解。因为使用回头的方式只会增加偶数个(或者)。那么永远满足不了(和)数量相等的条件。用线段树维护一下前缀和,(就是1,)就是-1。那么我们知道一个字符串满足括号匹配的条件就是(和)数量相等,并且没有一个前缀和小于0的。我们记录((出现的位置和))出现的位置,那么当原始)数量大于(时,肯定是在第一个((处做增量,并且保证出现第一个((之前的前缀和都不小于0,然后再往后走。那么要加多少个(呢,其实就是求最小的前缀和就是需要加多少(满足所有前缀和都不小于0,然后这个时候可能)的数量大于(的数量,所以我们需要找到))最后出现的位置,然后再这里做增加。假设((出现的位置是(i-1,i),那么在(i+1,n)中肯定没有)),所以要使得(i+1,n)满足条件必须是(和)交替出现的情况。也就是n-i是偶数并且((最后出现的位置小于))最后出现的位置。
#include <bits/stdc++.h>
using namespace std;
#define k_m (k / 2 + 1)
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int mx = 2e5 + 10;
const int mod = 1e9 + 7;
using ll = long long;
char s[mx];
int mtree[mx<<3];
int pre[mx];
set <int> s1, s2;
int lazy[mx<<3];
void build(int l, int r, int rt)
{
if (l == r) {
mtree[rt] = pre[l];
return ;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
mtree[rt] = min(mtree[rt<<1], mtree[rt<<1|1]);
}
void update_lazy(int rt)
{
if (lazy[rt]) {
mtree[rt<<1] += lazy[rt];
lazy[rt<<1] += lazy[rt];
mtree[rt<<1|1] += lazy[rt];
lazy[rt<<1|1] += lazy[rt];
lazy[rt] = 0;
}
}
void update(int l, int r, int rt, int L, int R, int v)
{
if (L <= l && r <= R) {
mtree[rt] += v;
lazy[rt] += v;
return ;
}
int mid = (l + r) >> 1;
update_lazy(rt);
if (L <= mid)
update(lson, L, R, v);
if (R > mid)
update(rson, L, R, v);
mtree[rt] = min(mtree[rt<<1], mtree[rt<<1|1]);
}
int query(int l, int r, int rt, int L, int R)
{
if (r < l) {
return 0;
}
if (L <= l && r <= R) {
return mtree[rt];
}
int mid = (l + r) >> 1;
update_lazy(rt);
if (L <= mid && R > mid)
return min(query(lson, L, R), query(rson, L, R));
if (L <= mid)
return query(lson, L, R);
return query(rson, L, R);
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
scanf("%s", s+1);
for (int i=1;i<=n;i++) {
pre[i] = pre[i-1];
if (s[i] == '(')
pre[i]++;
else
pre[i]--;
if (s[i] == s[i-1]) {
if (s[i] == '(') {
s1.insert(i);
} else
s2.insert(i);
}
}
build(1, n, 1);
while (m--) {
int v;
scanf("%d", &v);
if (s[v] == '(') {
update(1, n, 1, v, n, -2);
if (s[v] == s[v-1]) {
s1.erase(v);
} else if (v != 1)
s2.insert(v);
if (s[v+1] == s[v]) {
s1.erase(v+1);
} else if (v != n)
s2.insert(v+1);
s[v] = ')';
} else {
update(1, n, 1, v, n, 2);
if (s[v] == s[v-1]) {
s2.erase(v);
} else if (v != 1)
s1.insert(v);
if (s[v+1] == s[v]) {
s2.erase(v+1);
} else if (v != n)
s1.insert(v+1);
s[v] = '(';
}
//if (n == 16 && m + 65539 == 131054) { puts(s+1); }
if (n & 1) {
puts("NO");
continue;
}
int mu = mtree[1];
int lf = s1.size()? *s1.begin(): n;
if (query(1, n, 1, 1, lf) < 0) {
puts("NO");
} else {
int rl = s2.size()? *s2.rbegin(): 0;
int ll = s1.size()? *s1.rbegin(): 0;
puts((rl >= ll && (n - rl) % 2 == 0)? "YES": "NO");
}
}
return 0;
}
E - Count Supersequences
解题思路:可以证明其实答案跟n序列的值无关。然后答案反过来算就是k^m减去不包含n序列的b序列个数。我们可以去枚举包含最长长度为[0,n)的n序列的b序列。也就是,用快速幂求一下就行了。时间复杂度O(n*logn)
#include <bits/stdc++.h>
using namespace std;
const int mx = 1e6 + 10;
const int mod = 1e9 + 7;
using ll = long long;
ll qpow(ll x, ll y)
{
ll ans = 1;
while (y) {
if (y & 1) ans = ans * x % mod;
y >>= 1;
x = x * x % mod;
}
return ans;
}
ll inv[mx];
ll C(int n, int m)
{
return inv[n] * qpow(inv[n-m], mod-2) % mod * qpow(inv[m], mod-2) % mod;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n, m, k, v;
scanf("%d%d%d", &n, &m, &k);
for (int i=1;i<=n;i++) {
scanf("%d", &v);
}
ll ans = qpow(k, m);
ll cmi = 1;
for (int i=0; i<n; i++) {
ans -= cmi * qpow(k-1, m - i) % mod;
ans = (ans + mod) % mod;
cmi = cmi * (m - i) % mod * qpow(i+1, mod - 2) % mod;
}
printf("%lld\n", ans);
}
return 0;
}