牛客小白月赛95

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:这题要用到线段树(我不会哈哈,到时候会了在补)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值