Codeforces Global Round 21
复健场,类似的粗心不该再犯!
A、NIT orz!
Des
Solution
没啥好说的,通过观察,找到最大ai | m即可
Code
void solve()
{
cin >> n >> z;
for(int i = 1; i <= n; ++i) cin >> a[i];
int mx = 0;
for(int i = 1; i <= n; ++i) mx = max(mx, a[i] | z);
cout << mx << "\n";
}
B、NIT Destroys the Universe
Des
给你一个数组,每次选择一段区间[l, r],这段区间里面所有数变成该区间的MEX
Solution
真的很呆,被样例误解了,被坑了,
原本以为以0为隔板,有多少段连续不是0,就是答案,事实是最多两次,整段的mex肯定相同,然后再来一次就可以变成0,其他情况特判就行了。
Code
void solve()
{
cin >> n;
for(int i = 1; i <= n; ++i)
{
cin >> a[i];
}
int ans = 0;
for(int i = 1; i <= n; ++i)
{
if(a[i] != 0)
{
int j = i;
while(a[j] != 0 && j <= n) ++j;
ans++;
i = j - 1;
}
if(ans >= 2) break;
}
cout << (ans <= 1 ? ans : 2) << "\n";
}
C、Fishingprince Plays With Array
Des
给你两个数组a, b和一个数字k,你可以对a进行操作。
1、让ai能整除k的数,变成k个ai / k
2、将k个相同连续的数字合成,替换到a数组中
问是否最后a数组能和b数组都相同。
Solution
直接暴力拆a,b的每一个数,直到最后不能再拆为之,最后看两个数组是否相同,这里如果k很小,会爆内存。我们设计一个pair,就是值的x的最小因子出现了多少次,每次合并pair,就不会MLE了,本人因为if自己粗心,一直wa。。。
Code
void solve()
{
cin >> n >> k;
int x;
vector<pair<int, int> > v1;
for(int i = 1; i <= n; ++i)
{
int cnt = 1;
cin >> x;
while(x % k == 0)
{
cnt *= k;
x /= k;
}
if(v1.size())
{
auto& v = v1.back();
if(v.second == x) v.first += cnt;
else v1.push_back({cnt, x});
}
else v1.push_back({cnt, x});
}
cin >> m;
vector<pair<int, int> > v2;
for(int i = 1; i <= m; ++i)
{
int cnt = 1;
cin >> x;
while(x % k == 0)
{
cnt *= k;
x /= k;
}
if(v2.size())
{
auto& v = v2.back();
if(v.second == x) v.first += cnt;
else v2.push_back({cnt, x});
}
else v2.push_back({cnt, x});
}
if(v1.size() != v2.size()) cout << "No\n";
else
{
for(int i = 0; i < v1.size(); ++i)
{
if( v1[i].first != v2[i].first || v1[i].second != v2[i].second)
{
cout << "No\n";
return;
}
}
cout << "Yes\n";
}
}
D、Permutation Graph
Des
给你一个1-n的任意排列组合,如果一个[l, r]区间,最小值是a[l], 最大值是a[r],则存在一个l->r的无向边。
Solution
建一颗能查询最大最小值的线段树,每次递归,找当前区间跨度最长的一段线段,然后不断递归。
Code
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 100;
int n, a[N], pos[N];
struct tnode
{
int l, r, mx, mn;
};
struct segment_tree
{
tnode t[N << 2];
void pushup(int root)
{
int ch = root << 1;
t[root].mx = max(t[ch].mx, t[ch + 1].mx);
t[root].mn = min(t[ch].mn, t[ch + 1].mn);
}
void build(int root, int l, int r)
{
t[root].l = l;
t[root].r = r;
if(l != r)
{
int ch = root << 1;
int mid = l + r >> 1;
build(ch, l, mid);
build(ch + 1, mid + 1, r);
pushup(root);
}
else
{
t[root].mn = t[root].mx = a[l];
}
}
int query_max(int root, int l, int r)
{
if(t[root].l >= l && t[root].r <= r)
{
return t[root].mx;
}
int ch = root << 1;
int mid = t[root].l + t[root].r >> 1;
if(r <= mid) return query_max(ch, l, r);
else if(l > mid) return query_max(ch + 1, l, r);
else return max(query_max(ch, l, mid), query_max(ch + 1, mid + 1, r));
}
int query_min(int root, int l, int r)
{
if(t[root].l >= l && t[root].r <= r)
{
return t[root].mn;
}
int ch = root << 1;
int mid = t[root].l + t[root].r >> 1;
if(r <= mid) return query_min(ch, l, r);
else if(l > mid) return query_min(ch + 1, l, r);
else return min(query_min(ch, l, mid), query_min(ch + 1, mid + 1, r));
}
} st;
int cal(int l, int r)
{
if(l + 1 == r) return 1;
if(l >= r) return 0;
int mxval = st.query_max(1, l, r);
int mnval = st.query_min(1, l, r);
int L = pos[mxval], R = pos[mnval];
if(L > R) swap(L, R);
return cal(l, L) + 1 + cal(R, r);
}
void solve()
{
cin >> n;
for(int i = 1; i <= n; ++i) cin >> a[i], pos[a[i]] = i;
if(n == 1)
{
cout << "0\n";
return;
}
st.build(1, 1, n);
cout << cal(1, n) << "\n";
int m;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0);
int t;
cin >> t;
while(t--) solve();
return 0;
}

浙公网安备 33010602011771号