Educational Codeforces Round 76
A. Two Rival Students
让两个人向两侧走就好了。
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n , x , a , b;
cin >> n >> x >> a >> b;
if( a > b ) swap( a , b );
while( x > 0 && a > 1 ) x -- , a --;
while( x > 0 && b < n ) x -- , b ++;
cout << b-a<<"\n";
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int t;
cin >> t;
while( t -- )
solve();
return 0;
}
B. Magic Stick
只要能让\(a\)变的比\(b\)大就一定有解。
\(a\)不能无限变大的情况只有\(1,2,3\)特判即可
#include <bits/stdc++.h>
using namespace std;
void solve(){
int x , y;
cin >> x >> y;
if( x == 1 && y != 1 ) cout << "NO\n";
else if( x == 3 && y > 3 ) cout << "NO\n";
else if( x == 2 && y > 3 ) cout << "NO\n";
else cout << "YES\n";
return ;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int t;
cin >> t;
while( t -- )
solve();
return 0;
}
C. Dominated Subarray
可以知道的是,所谓的众数只要保证子区间有两个相同的数,其他数只有一个即可,并且其他情况一定可以通过拆分区间变成这种最简的情况。
这种情况下用一个双指针就可以\(O(n)\)枚举区间求解。
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n;
cin >> n;
vector<int> vis(n+1) , a(n+1);
for( int i = 1 ; i <= n ; i ++ )
cin >> a[i];
int res = INT_MAX;
for( int l = 1 , r = 0 , f = 0; l <= n ; l ++ ){
while( r+1 <= n && f == 0 ){
r ++ , vis[a[r]] ++;
if( vis[a[r]] == 2 ) f = 1;
}
if( f == 0 ) break;
res = min( res , r-l+1);
vis[ a[l] ] --;
if( vis[a[l]] == 1 ) f = 0;
}
if( res == INT_MAX ) res = -1;
cout << res << "\n";
return ;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int t;
cin >> t;
while( t -- )
solve();
return 0;
}
D. Yet Another Monster Killing Problem
维护相同体力下,英雄的最大攻击力。并且体力更小的可以被体力更大的覆盖,因此还可以求一个后缀最大值。
这样的话就可以用一个快慢指针的形式\(O(n)\)的贪心一下,每次在满足可以覆盖当前怪兽的情况下,尽可能的选择体力更好的。
#include <bits/stdc++.h>
using namespace std;
void solve() {
int n, m;
cin >> n;
vector<int> a(n), s(n + 1);
for (auto &i: a)
cin >> i;
cin >> m;
for (int i = 0, x, y; i < m; i++)
cin >> x >> y, s[y] = max(s[y], x);
for (int i = n - 1; i >= 0; i--)
s[i] = max(s[i], s[i + 1]);
int res = 0;
for (int pos = 0, t, tp; pos < n;) {
res++, t = pos, tp = a[t];
while (t < n && tp <= s[t - pos + 1]) t++, tp = max(tp, a[t]);
if (t == pos) {
cout << "-1\n";
return;
}
pos = t;
}
cout << res << "\n";
return;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
E. The Contest
dp,\(f[i][0/1/2]\)表示前\(i\)个数且第\(i\)个数在前缀中间后缀的最小交换次数。
\(f[i][j]\)可以从\(f[i-1][k]\)转移,条件是\(j\ge k\),代价是\(i\)是否原本在\(j\)上
#include <bits/stdc++.h>
using namespace std;
#define int long long
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int n1, n2, n3, n;
cin >> n1 >> n2 >> n3, n = n1 + n2 + n3;
vector<int> a(n + 1);
for (int i = 1, x; i <= n1; i++)
cin >> x, a[x] = 0;
for (int i = 1, x; i <= n2; i++)
cin >> x, a[x] = 1;
for (int i = 1, x; i <= n3; i++)
cin >> x, a[x] = 2;
vector<array<int, 3>> f(n + 1, {INT_MAX, INT_MAX, INT_MAX});
f[0][0] = f[0][1] = f[0][2] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= 2; j++)
for (int k = 0; k <= j; k++)
f[i][j] = min(f[i][j], f[i - 1][k] + (a[i] != j));
}
cout << min({f[n][0], f[n][1], f[n][2]});
return 0;
}
F. Make Them Similar
首先把所有是数字分成\(a_i,b_i\)两个部分,然后枚举数字\(x\),记\(c_i,d_i\)分别是\(a_i,b_i\)异或\(x\)后1 的数量,如果\(x\)满足则有\(c_1+d_1=c_i+d_i\),可以整理为\(c1-c_i=d_i-d_1\)。这样我们可以像枚举高十五位,用 map 统计所有的答案,然后再枚举低十五位,直接在map里面检查答案是否存在即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int M = (1 << 15) - 1;
#define lowbit(x) ( x & -x )
int cnt(int x) {
int ans = 0;
while (x) ans++, x -= lowbit(x);
return ans;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n), b(n);
for (int i = 0, x; i < n; i++)
cin >> x, a[i] = x & M, b[i] = x >> 15;
map<vector<int> , int> vis;
for (int i = 0, t; i <= M; i++) {
t = cnt(i ^ a[0]);
vector<int> v;
for (int j = 1; j < n; j++)
v.push_back(t - cnt(i ^ a[j]));
vis[v] = i;
}
for( int i = 0 , t ; i <= M ; i ++ ){
t = cnt( i ^ b[0] );
vector<int> v;
for( int j = 1 ; j < n; j ++ )
v.push_back( cnt( i ^ b[j]) - t);
if( vis.count(v) ){
cout << ((i<<15) | vis[v]) << "\n";
return 0;
}
}
cout << "-1\n";
return 0;
}