A.Make It Zero
主要题意: 给定一串数字,通过异或运算可以使区间[l,r]变成相同的数,求最少使全串变成0的修改次数与l,r取值。
思路:其实这道题思路很简单:相同的数异或为0
我们可以知道:如果区间所取数量为偶数时,通过一次异或可以变成相同数,再进行一次异或就可以全部变成0;如果区间为奇数时,我们可以取n-1进行2次异或为全0,再将一个0与后奇数部分结合,再进行两次就能全为0了!
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int a[N];
int n;
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> n;
int sum = 0;
memset(a, 0, sizeof(a));
for (int i = 1; i <= n; i++)
{
cin >> a[i];
sum ^= a[i];
}
if (sum == 0)
{
cout << 1 << endl;
cout << 1 << " " << n << endl;
continue;
}
if (n % 2 == 0)
{
cout << 2 << endl;
cout << 1 << " " << n << endl;
cout << 1 << " " << n << endl;
}
else
{
cout << 4 << endl;
cout << 1 << " " << n - 1 << endl;
cout << 1 << " " << n - 1 << endl;
cout << n - 1 << " " << n << endl;
cout << n - 1 << " " << n << endl;
}
}
return 0;
}
B.2D Traveling
题目大意:度假出行,n个城市,前k个是主要城市,主要城市之间出行不花钱,其余为非主要城市,非主要城市和主要城市之间出行要花费一定钱(曼哈顿距离),非与非之间也是如此,求从a城到b城最小花费!
思路:刚开始一看最短距离,想到Dij,但发现非与主或非与非之间的花费是曼哈顿距离,直接就是最优,就不需要搜索了,直接枚举考虑a,b分布情况。
(1). a,b都是主要城市,花费直接为0,输出
(2). a,b都不是主要城市,先求出a,b之间的花费ans,再求从主要城市到a,b各自的最少花费,相加后与ans进行比较,取最小值
(3)a,b有一个是主要城市,a到b与b到a是一样的,所以我们可以假定a<b,即a是主要城市,b是非主要,
这里可以直接枚举从主要城市到b的最小花费,取最小值。
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 10;
int n, k, a, b;
struct node {
ll x, y;
}Cy[N];
ll Dis(int l, int r)
{
return (ll)abs(Cy[l].x - Cy[r].x) + (ll)abs(Cy[l].y - Cy[r].y);
}
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> n >> k >> a >> b;
for (int i = 1; i <= n; i++)
{
cin >> Cy[i].x >> Cy[i].y;
}
if (a <= k && b <= k)
{
cout << 0 << endl;
continue;
}
if (a>k&&b>k)
{
ll ans = Dis(a, b);
ll ma = 1e18, mb = 1e18;
for (ll i = 1; i <= k; i++)
{
ma = min(ma, Dis(i, a));
mb = min(mb, Dis(i, b));
}
cout << min(ans, ma + mb) << endl;
continue;
}
if (a > b) swap(a, b);
ll ans = 1e18;
for (int i = 1; i <= k; i++) ans = min(ans, Dis(i, b));
cout << ans << endl;
}
return 0;
}
C.Fill in the Matrix
题目大意:就是给你矩阵的行数和列数,定义每一行的值[0,m-1]之间且不重复,使vi=MEX(i列中未出现的最小>=0整数),最后s=MEX(v组中未出现最小>=0整数),设计矩阵每行每列使s取到最大值!
思路:因为要是使s尽可能的大,所以我们希望每个vi也能做到不重复。如果我们假设v1=0,v2=1,v3=2...我们应该怎么实现呢? 其实很简单,我们可以假设第一行的数为1,2,3...m-1,0,
然后依次左移一位,我们可以发现就可以构造出上面那个V序列,但是需要注意的是我们左移的次数是有限制的,因为过多的移动会使每个数在一列中都能出现,此时就无法得到最大答案,只能得0。次数其实很好判断,num=min(n,m-1),不多赘述(移一移就知道了),然后我们用第一行去覆盖未赋值的行数,就能实现了。M=1是一个特例要分出来解,记得不要忘了这个也要输出矩阵(zzz赛时没输wa了两次OVO)!
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n, m;
vector<int>a[200010];
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> n >> m;
for (int i = 0; i<m; i++)
{
a[1].push_back(i);
}
for (int i = 2; i <= min(m - 1, n); i++)
{
for (int j = 0; j < m; j++)
{
a[i].push_back(a[i - 1][(j + 1) % m]);
}
}
for (int i = min(m - 1, n) + 1; i <= n; i++)
{
a[i] = a[1];
}
if (m == 1)
{
cout << 0 << endl;
for (int i = 1; i <= n; i++) cout<<0<< endl;
for (int i = 1; i <= n;i++) a[i].clear();
continue;
}
else
{
cout << min(m,n + 1) << endl;
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < m; j++)
{
if (j == m - 1) cout << a[i][j];
else cout << a[i][j] << " ";
}
cout << endl;
}
for (int i = 1; i <= n; i++) a[i].clear();
}
}
return 0;
}
比赛做了一个小时就润了,目前就先更A,B,C吧