Codeforces Round 888 (Div. 3)
A. Escalator Conversations
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int n , m , k ,H;
cin >> n >> m >> k >> H;
vector<int> h(n);
int res = 0;
for( int h , i = 1 ; i <= n ; i ++ ){
cin >> h;
h = abs( h - H );
if( h % k != 0 || h == 0 )continue;
if( (h / k) < m ) res ++ ;
}
cout << res << "\n";
return ;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while( t -- )
solve();
return 0;
}
B. Parity Sort
把奇偶分别排序在重新放回去
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n;
cin >> n;
vector<int> a(n), b, c;
for (int i = 0, x; i < n; i++) {
cin >> x;
a[i] = x & 1;
if (a[i]) b.push_back(x);
else c.push_back(x);
}
sort(b.begin(), b.end());
sort(c.begin(), c.end());
for( int i = 0 , j = 0 , k = 0 ; i < n ; i ++ ){
if( a[i] ) a[i] = b[j] , j ++;
else a[i] = c[k] , k ++;
}
for( int i = 1 ; i < n ; i ++ ){
if( a[i] < a[i-1] ) {
cout << "NO\n";
return ;
}
}
cout << "YES\n";
return ;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
另一种更简洁的思路就是排序后,判断排序前后数组每一位的奇偶性是否相同
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n;
cin >> n;
vector<int> a(n);
for (auto &i: a) cin >> i;
auto b = a;
sort(b.begin(), b.end());
for (int i = 0; i < n; i++)
if ((a[i] - b[i]) & 1) {
cout << "NO\n";
return;
}
cout << "YES\n";
return;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
C. Tiles Comeback
贪心的选择前缀和c[1]
相同的、后缀和c[n]
相同的。
特判一下c[1]==c[n]
的情况
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n, k;
cin >> n >> k;
vector<int> c(n + 1);
for (int i = 1; i <= n; i++) cin >> c[i];
int l = -1, r = -1;
for (int i = 1, cnt = 0; l == -1 && i <= n; i++) {
if (c[i] == c[1]) cnt++;
if (cnt == k) l = i;
}
for (int i = n, cnt = 0; r == -1 && i >= 1; i--) {
if (c[i] == c[n]) cnt++;
if (cnt == k) r = i;
}
if (l == -1 || r == -1)
cout << "NO\n";
else if (c[1] == c[n])
cout << "YES\n";
else if (l < r)
cout << "YES\n";
else
cout << "NO\n";
return;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
D. Prefix Permutation Sums
先差分回去,统计缺少的数字数量。
- 缺大于 2 个 ,无解
- 缺2个,检查缺的数字之和和多的数字之和是否相同
- 缺 1 个,此时多的数字应该是0
- 不缺,不存在
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n;
cin >> n;
vector<int> a(n), vis(n + 1);
int x = 0, y = n * (n + 1) / 2, z = n;
for (int i = 1; i < n; i++) cin >> a[i];
for (int i = n - 1; i > 1; i--) a[i] = a[i] - a[i - 1];
for (int i = 1; i < n; i++) {
if (a[i] > n) x += a[i];
else if (vis[a[i]] == 0) vis[a[i]] = 1, y -= a[i], z--;
else x += a[i];
}
if (z > 2) cout << "NO\n";
else if (x == y) cout << "YES\n";
else if (z == 1 && x == 0) cout << "YES\n";
else cout << "NO\n";
return;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
E. Nastya and Potions
把无限供应的药品的cost修改为 0,合成药品的关心其实可以看做有向图,建反向图,在反向图上跑拓扑序,根据拓扑序去计算每种药品获得的最小代价。
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n, k;
cin >> n >> k;
vector<int> cost(n + 1), v(n + 1, -1);
for (int i = 1; i <= n; i++)
cin >> cost[i];
for (int i = 1, x; i <= k; i++)
cin >> x, cost[x] = 0;
vector<vector<int>> e(n + 1), g(n + 1);
vector<int> inner(n + 1);
for (int i = 1; i <= n; i++) {
cin >> inner[i];
for (int j = 0, x; j < inner[i]; j++)
cin >> x, e[i].push_back(x), g[x].push_back(i);
}
queue<int> q;
for (int i = 1; i <= n; i++)
if (inner[i] == 0) q.push(i);
while (!q.empty()) {
int i = q.front();
q.pop();
if (!e[i].empty()) {
int sum = 0;
for (auto j: e[i])
sum += cost[j];
cost[i] = min(cost[i], sum);
}
for (auto j: g[i]) {
inner[j]--;
if (inner[j] == 0) q.push(j);
}
}
for (int i = 1; i <= n; i++)
cout << cost[i] << " ";
cout << "\n";
return;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
F. Lisa and the Martians
首先\((a_i\oplus x)\&(a_j\oplus x )= a_i\odot a_j =\overline{(a_i\oplus a_j)}= y\),所以\(y\)实际上就是同或最大值或者异或的最小值。
同时可以知道\(x=(a_i \oplus y ) | (a_j \oplus y)\)
数组中任意两数异或的最小值一定是排序后的相邻数的异或
根据这个性质就很好求了。
求异或最小值
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef bitset<30> Num;
vector<int> Temp(31);
void solve() {
int n, k;
cin >> n >> k;
int T = (1ll << k) - 1;
vector<pair<int,int>> a;
for( int i = 1 , x ; i <= n ; i ++ )
cin >> x , a.emplace_back( x , i );
sort( a.begin(), a.end() );
int l , r , res = INT_MAX , val;
for( int i = 1 ; i < n ; i ++ ){
if( res > (a[i].first^a[i-1].first)){
res = a[i].first ^ a[i-1].first;
l = a[i].second , r = a[i-1].second;
val = T ^ ( a[i].first | a[i-1].first );
}
}
cout << l << " " << r << " " << val << "\n";
return;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
求同或最大值
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef bitset<30> Num;
vector<int> Temp(31);
void solve() {
int n, k;
cin >> n >> k;
int T = (1ll << k) - 1;
vector<pair<int, int>> a;
for (int i = 1, x; i <= n; i++)
cin >> x, a.emplace_back(x, i);
sort(a.begin(), a.end());
int l, r, res = INT_MIN, val;
for (int i = 1, t; i < n; i++) {
t = (~(a[i].first ^ a[i - 1].first)) & T;
if (t > res) {
res = t;
l = a[i].second, r = a[i - 1].second;
val = (a[i].first ^ t) | (a[i - 1].first ^ t);
}
}
cout << l << " " << r << " " << val << "\n";
return;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
G. Vlad and the Mountains
首先可以知道的是,从\(a\)出发可能到达的点\(i\)一定满足\(h[i]\le h[a] + e\)
对于每条边\(i\),记\(w_i=\max( h[u_i],h[v_i])\),这样的话从\(a\)出发可以走的边一定满足\(w_i\le h[a]+e\)
取所用复合条件的边,用并查集维护,最后检查 \(a,b\)是否联通即可。
为了优化,可以离线询问,按照\(h[a]+e\)从小到大的顺序回答即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
class dsu {
private:
vector<int> fa;
public:
dsu(int n = 1) {
fa = vector<int>(n + 1, -1), fa[0] = 0;
}
int getfa(int x) {
if (fa[x] < 0) return x;
return fa[x] = getfa(fa[x]);
}
void merge(int x, int y) {
x = getfa(x), y = getfa(y);
if (x == y) return;
if (fa[x] > fa[y]) swap(x, y);
fa[x] += fa[y], fa[y] = x;
}
bool same(int x, int y) {
x = getfa(x), y = getfa(y);
return (x == y);
}
};
void solve() {
int n, m;
cin >> n >> m;
vector<int> h(n + 1);
for (int i = 1; i <= n; i++) cin >> h[i];
vector<array<int, 3>> edge(m);
for (auto &[w, x, y]: edge)
cin >> x >> y, w = max(h[x], h[y]);
sort(edge.begin(), edge.end());
int q;
cin >> q;
vector<array<int, 4>> Q(q);
for (int i = 0, a, b, e; i < q; i++)
cin >> a >> b >> e, e += h[a], Q[i] = {e, a, b, i};
sort( Q.begin(), Q.end() );
dsu d(n);
vector<bool> res(q);
int t = 0;
for( const auto & [ e , a , b , id ] : Q ){
for ( ; t < edge.size() && edge[t][0] <= e ; t ++ )
d.merge( edge[t][1] , edge[t][2] );
if( d.same( a , b ) ) res[id] = true;
}
for (auto i: res)
if (i) cout << "YES\n";
else cout << "NO\n";
cout << "\n";
return;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}