A - Ilya and a Colorful Walk
贪心的选取与首元素不相同的最远位置和与尾元素不相同的最远位置.
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
const int N = 3e5 + 20;
int n, a[N];
int main()
{
IOS;
cin >> n;
for(int i = 1; i <= n; ++ i) cin >> a[i];
int res = 0;
for(int i = 2; i <= n; ++ i)
if(a[i] != a[1]) res = max(res, i - 1);
for(int i = 1; i < n; ++ i)
if(a[n] != a[i]) res = max(res, n - i);
cout << res << endl;
return 0;
}
B - Alyona and a Narrow Fridge
二分答案,排序后两个一组判断是否合法.
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
const int N = 2e5 + 20;
int n, h, a[N];
bool check(int x)
{
std::vector<int> v;
for(int i = 1; i <= x; ++ i)
v.push_back(a[i]);
int t = h;
sort(v.begin(), v.end(), greater<int>());
for(int i = 0; i < (int)v.size(); i += 2)
{
if(t < v[i]) return 0;
t -= v[i];
}
return 1;
}
int main()
{
IOS;
cin >> n >> h;
for(int i = 1; i <= n; ++ i) cin >> a[i];
int l = 1, r = n, res = 1;
while(l <= r)
{
int mid = (l + r) >> 1;
if(check(mid))
{
res = mid;
l = mid + 1;
}
else r = mid - 1;
}
cout << res << endl;
return 0;
}
C - Ramesses and Corner Inversion
对每一个方格进行 (2 imes 2)的操作,最后判断最后一行和最后一列是否和目标一致即可.
也可以考虑操作的特殊性质,每次变换4个角的元素,各行和各列元素个数的奇偶性不发生变化.
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
const int N = 500 + 20;
int n, m;
int A[N][N], B[N][N];
bool check()
{
for(int i = 1; i < n; ++ i)
{
for(int j = 1; j < m; ++ j)
if(A[i][j] != B[i][j])
{
A[i][j] ^= 1;
A[i + 1][j] ^= 1;
A[i][j + 1] ^= 1;
A[i + 1][j + 1] ^= 1;
}
if(A[i][m] != B[i][m]) return 0;
}
for(int i = 1; i <= m; ++ i)
if(A[n][i] != B[n][i]) return 0;
return 1;
}
int main()
{
IOS;
cin >> n >> m;
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= m; ++ j)
cin >> A[i][j];
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= m; ++ j)
cin >> B[i][j];
if(check()) puts("Yes");
else puts("No");
return 0;
}
D - Frets On Fire
对原数组排序去重,做差分后排序,二分找到第一个大于区间长度的位置算前半段和后半段的贡献即可,前半段的贡献用差分序列的前缀和优化.
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
const int N = 2e5 + 20;
int n, m;
LL sum[N], v[N];
int main()
{
IOS;
cin >> n;
vector<LL> s(n);
for(int i = 0; i < n; ++ i) cin >> s[i];
sort(s.begin(), s.end());
s.erase(unique(s.begin(), s.end()), s.end());
n = s.size();
for(int i = 1; i < n; ++ i)
v[i] = s[i] - s[i - 1];
sort(v + 1, v + n + 1);
for(int i = 1; i <= n; ++ i)
sum[i] = sum[i - 1] + v[i];
cin >> m;
while(m -- )
{
LL x, y, res = 0;
cin >> x >> y;
int pos = upper_bound(v + 1, v + n + 1, y - x + 1) - v;
// cout << "!" << pos << endl;
res += sum[pos - 1];
res += (n - pos + 1) * (y - x + 1);
res += y - x + 1;
cout << res << " ";
}
return 0;
}
E - Pavel and Triangles
对于给定的边,组成三角形必须至少有两条一样长的边,长度小的边可以选择的比它小的边更少,
所以贪心的先从长度小的边开始枚举,如果能找到比它小的边还没用完,则尽可能选比它小的边加上两条该边组成三角形,否则,用三条该边组成三角形.
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
const int N = 3e5 + 20;
int n;
int main()
{
IOS;
cin >> n;
LL res = 0, last = 0;
for(int i = 1; i <= n; ++ i)
{
int x;
cin >> x;
LL k = min((LL)x / 2, last);
res += k;
x -= k * 2;
last -= k;
res += x / 3;
last += x % 3;
}
cout << res << endl;
return 0;
}
2021.1.13