C
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int a[N],s[5];
int main()
{
int n;
cin>>n;
if(n==1)//当元素数量n=1时:不可操作,输出:-1
{
cout<<-1;
return 0;
}
for(int i=1;i<=n;i++)
{
cin>>a[i];
//if(a[i]==1)s[1]++;
//else s[0]++;
}
if(a[1]==a[n])//当开头元素等于末尾元素时: 操作数为1
{
cout<<1;
return 0;
}
//当第i位元素和开头元素相等,并且i+1位元素和结尾元素相等时,操作数为:2。
for(int i=2;i<n-1;i++)
{
if(a[i]==a[1]&&a[i+1]==a[n])
{
cout<<2;
return 0;
}
}
cout<<-1;//都不符合的情况,为不可操作,输出:-1
//return 0;
}
D:用到了差分数组
炸弹的范围就是图中的矩形范围,如果一个个点的枚举会tle,所以我们用差分数组一行行枚举
所以x-r<=i<=x+r;蓝色线就是|x-i|,由于小三角是等腰三角形,所以l=r-|x-i|。之后用差分就行
#include<bits/stdc++.h>
using namespace std;
int mp[6010][6010];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n,m;
cin>>n>>m;
int x,y,r;
while(m--)
{
cin>>x>>y>>r;
//遍历x方向上的曼哈顿距离
for(int i=x-r;i<=x+r;i++)
{
if(i<1||i>n)continue;
//看图
int l=r-abs(x-i);
mp[i][max(1,y-l)]++;//防止越界
mp[i][min(n+1,y+l+1)]--;
}
}
int sum=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
mp[i][j]+=mp[i][j-1];//前缀和预处理
sum+=(mp[i][j]%2);
}
cout<<sum;
return 0;
}
E:dp,看代码注释
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int a[N],dp[N],mn[N];//dp消除前i项要的最小操作数
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n;
cin>>n;
memset(mn,0x3f,sizeof mn);
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
dp[i]=mn[a[i]]+1;
//更新为与当前值a[i]相等的值的前面部分被消除的最小值再加1
//如3 7 3 7 4 3 7,最后一个7由前一个7前面部分的最小操作值更新而来
//mn[a[i]]表示a[i]前面部分被消除所需的最小次数
//mn[a[i]]表示在所有值为a[i]的部分的前面被削掉要的最小操作数
mn[a[i]]=min(mn[a[i]],dp[i-1]);
//即mn[7]取得是所有位置的7前面部分被消除的最小值
}
if(dp[n]>=1e6)cout<<-1;
else cout<<dp[n];
return 0;
}
F:异或炸弹
知识点:切比雪夫距离和曼哈顿距离的转化,,二维前缀和差分
切比雪夫距离和曼哈顿距离的转化
曼哈顿距离转切比雪夫( x + y , x − y )
切比雪夫转曼哈顿距离( x + y / 2 , x − y / 2 )
#include<bits/stdc++.h>
using namespace std;
const int N = 6e3 + 10;
int f[N][N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n,m;
cin >> n >> m;
for(int i = 1; i <= m; i ++)
{
int x, y, r;
cin >> x >> y >> r;
// 曼哈顿距离转换成切比雪夫距离
// +3000坐标偏移为防止出现负数
int nx = x + y, ny = x - y + 3000;
//转换成切比雪夫距离后,便于差分
//二维差分
f[max(1, nx - r)][max(1, ny - r)] ^= 1;
f[min(6000, nx + r + 1)][max(1, ny-r)] ^= 1;
f[max(1, nx-r)][min(6000, ny + r + 1)] ^= 1;
f[min(6000, nx + r + 1)][min(6000, ny + r + 1)] ^= 1;
}
int ans = 0;
for(int i = 1; i <= 6000; i ++)
for(int j = 1; j <= 6000; j ++)
{
//二维前缀和
f[i][j] = f[i-1][j]^f[i-1][j-1]^f[i][j-1]^f[i][j];
//曼哈顿距离转换成切比雪夫距离
int x = (i + j - 3000) / 2, y = (i - j + 3000) / 2;
//判断值是否为1,是否越界
//(i+j)和(i-j)是否是偶数,因为转成切比雪夫把图放大了
//可能有一些不存在的点,原图边长是根号2变成了2
//所有要判断(i+j)和(i-j)是否是偶数排除不存在的点
//更详细可看B站牛客官方题解
if(f[i][j] && (i+j)%2==0 && (i-j)%2==0 && x > 0 && x <= n && y > 0 && y <= n)
ans ++;
}
cout << ans << '\n';
return 0;
}
G:这题要用到线段树(我不会哈哈,到时候会了在补)