A - Intersection
题意
给出两条线段,求交集长度
题解
暴力
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <bits/stdc++.h> using namespace std;using LL = long long ;const int N = 2e5 + 5 , MOD = 998244353 , INF = 0x3f3f3f3f ;signed main () { cin.tie (nullptr )->sync_with_stdio (false ); int l1, r1, l2, r2; cin >> l1 >> r1 >> l2 >> r2; vector< int > a (101 ) ; for (int i = l1; i <= r1; ++ i) { a[i] = 1 ; } int ans = 0 ; for (int i = l2; i <= r2; ++ i) { ans += a[i]; } if (ans) -- ans; cout << ans << '\n' ; return 0 ; }
B - Tournament Result
题意
一个二维矩阵,$A_{i,j}$为W
则$i$击败$j$,为L
则$i$败给$j$,为D
则$i$和$j$打成平局
求是否冲突
The table is said to be contradictory when some of the following holds:
There is a pair (i ,j ) such that Player i beat Player j , but Player j did not lose to Player i ;
There is a pair (i ,j ) such that Player i lost to Player j , but Player j did not beat Player i ;
There is a pair (i ,j ) such that Player i drew with Player j , but Player j did not draw with Player i .
题解
模拟
代码
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 #include <bits/stdc++.h> using namespace std;using LL = long long ;const int N = 1005 , MOD = 998244353 , INF = 0x3f3f3f3f ;int n;string s[N]; int dis[N][N];signed main () { cin.tie (nullptr )->sync_with_stdio (false ); cin >> n; for (int i = 0 ; i < n; ++ i) { cin >> s[i]; } bool safe = true ; for (int i = 0 ; i < n; ++ i) { for (int j = i + 1 ; j < n; ++ j) { if (s[i][j] == 'D' && s[j][i] != 'D' ) { safe = false ; } if (s[i][j] == 'W' && s[j][i] != 'L' ) { safe = false ; } if (s[i][j] == 'L' && s[j][i] != 'W' ) { safe = false ; } } } cout << (safe ? "correct" : "incorrect" ) << '\n' ; return 0 ; }
C - NewFolder(1)
题意
给出n
个字符串,要求以 $s_i+(\sum_{j=1}^{i-1}s_j==s[i])$ 的形式输出 n
个字符串
题解
模拟
代码
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 #include <bits/stdc++.h> using namespace std;using LL = long long ;const int N = 2e5 + 5 , MOD = 998244353 , INF = 0x3f3f3f3f ;int n;string s[N]; signed main () { cin.tie (nullptr )->sync_with_stdio (false ); cin >> n; string str; for (int i = 1 ; i <= n; ++ i) { cin >> s[i]; } map< string, int > cnt; for (int i = 1 ; i <= n; ++ i) { if (!cnt[s[i]]) { cout << s[i] << '\n' ; } else { cout << s[i] + '(' + to_string (cnt[s[i]]) + ')' << '\n' ; } ++ cnt[s[i]]; } return 0 ; }
D - Flipping and Bonus
题意
Takahashi
会投掷$n$次硬币,若第$i$次硬币为正面,则他会获得$X_i$元的奖励,同时给出$m$个附加奖励,当他每次连续投掷正面的次数为$C_i$时他会额外获得$Y_i$元的奖励,求Takahashi
能获得的最大钱数。
题解
我们定义$dp_{i,j}$为投掷第$i$次硬币后,连续正面次数为$j$的最大收益
若第$i$次投掷的是正面
$dp_{i,j}=dp_{i-1,j-1}+X_i$
若第$i$次投掷的是反面,那么连续正面次数重置为0
$dp_{i,0}=\max(dp_{i,0},dp_{i-1,j})$
接下来考虑额外奖励
$dp_{i,C_j}=\max\left( dp_{i,C_j},dp_{i-1,C_j-1+Y_j+X_i} \right)$
代码
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> using namespace std;using LL = long long ;const int N = 5005 , MOD = 998244353 , INF = 0x3f3f3f3f ;int n, m, x[N], c[N], y[N];LL dp[N][N]; signed main () { cin.tie (nullptr )->sync_with_stdio (false ); cin >> n >> m; for (int i = 1 ; i <= n; ++ i) { cin >> x[i]; } for (int i = 1 ; i <= m; ++ i) { cin >> c[i] >> y[i]; } for (int i = 1 ; i <= n; ++ i) { for (int j = 0 ; j <= i - 1 ; ++ j) { dp[i][j + 1 ] = dp[i - 1 ][j] + x[i]; dp[i][0 ] = max (dp[i][0 ], dp[i - 1 ][j]); } for (int j = 1 ; j <= m; ++ j) { if (c[j] <= i) { dp[i][c[j]] = max (dp[i][c[j]], dp[i - 1 ][c[j] - 1 ] + y[j] + x[i]); } } } LL ans = 0 ; for (int i = 1 ; i <= n; ++ i) { for (int j = 0 ; j <= n; ++ j) { ans = max (ans, dp[i][j]); } } cout << ans << '\n' ; return 0 ; }
E - Many Operations
题意
我们有一个初值$X$,以及$n$个操作$op, A_i$
若$op=1$ ,则令 $X= X$ & $A_i$
若$op=2$ ,则令 $X=X|A_i$
若$op=3$ ,则令 $X=X\bigoplus A_i$
我们令初值$X$进行了前$i$次操作后的值为$Y_i$,输出$Y_i(1 \leq i \leq n)$
题解
初一看,感觉是个很厉害的题,细想后发现可以对每一位分别考虑。
分别计算初始值每一位为$0$ 或 $1$,进行$i$次运算后的值,第$i$ 次的初始值为 $Y_{i-1}$ ,对 $Y_{i-1}$的每一位统计即可
代码
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 #include <bits/stdc++.h> using namespace std;using LL = long long ;const int N = 2e5 + 5 , MOD = 998244353 , INF = 0x3f3f3f3f ;int n, C;signed main () { cin.tie (nullptr )->sync_with_stdio (false ); cin >> n >> C; int X = (1 << 30 ) - 1 , Y = 0 ; for (int i = 1 ; i <= n; ++ i) { int op, x; cin >> op >> x; if (op == 1 ) { X &= x; Y &= x; } else if (op == 2 ) { X |= x; Y |= x; } else { X ^= x; Y ^= x; } LL ans = 0 ; for (int j = 0 ; j < 30 ; ++ j) { if (C >> j & 1 ) { ans |= (X >> j & 1 ) << j; } else { ans |= (Y >> j & 1 ) << j; } } cout << (C = ans) << '\n' ; } return 0 ; }
F - Sorting Color Balls
题意
给定$n$个元素,每个元素有一个值和一个颜色,每次操作可以交换相邻的两个元素,若这两个元素颜色不同,则需要消耗一点$cost$,询问通过操作将这$n$个元素按非递减排列所需要的最小$cost$
题解
首先不考虑颜色,其代价显然是数组的逆序对个数
现在加上颜色的限制,其代价就是总的逆序对个数减去同种颜色之间逆序对的个数,维护这个即可。
这里我用了非树状数组的方法来求同种颜色之间逆序对的个数,从后往前遍历,我们每次把$X_i$顺序插入$C_i$对应的数组,询问时我们查询当前的$X_i$位于$C_i$对应的数组第几个即可,$j>i$且$X_j<X_i$符合逆序对定义嘛
代码
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 #include <bits/stdc++.h> using namespace std;using LL = long long ;const int N = 3e5 + 5 , MOD = 998244353 , INF = 0x3f3f3f3f ;int n, c[N], x[N];vector< int > col[N]; struct FenWick { int n; vector< int > c; FenWick (int n) : n (n), c (n + 1 ) {} void add (int i, int d) { for (; i <= n; i += i & -i) { c[i] += d; } } void add (int l, int r, int d) { add (l, d); add (r + 1 , -d); } int get (int i) { int sum = 0 ; for (; i; i -= i & -i) { sum += c[i]; } return sum; } int get (int l, int r) { return get (r) - get (l - 1 ); } }; signed main () { cin.tie (nullptr )->sync_with_stdio (false ); cin >> n; for (int i = 1 ; i <= n; ++ i) { cin >> c[i]; } for (int i = 1 ; i <= n; ++ i) { cin >> x[i]; } LL ans = 0 ; FenWick k (n) ; for (int i = n; i >= 1 ; -- i) { ans += k.get (x[i] - 1 ); k.add (x[i], 1 ); ans -= upper_bound (col[c[i]].begin (), col[c[i]].end (), x[i] - 1 ) - col[c[i]].begin (); col[c[i]].insert (upper_bound (begin (col[c[i]]), end (col[c[i]]), x[i]), x[i]); } cout << ans << '\n' ; return 0 ; }