牛客小白月赛86DE

文章讨论了两个编程问题:使用BFS和DFS算法计算剪纸中由.连接形成长方形的数量,以及在一个连续区间内满足特定条件时最大化d和的问题。
摘要由CSDN通过智能技术生成

D剪纸

题意:剪纸中'.'连接成的长方形的个数(正方形是特殊的长方形)

思路:利用bfs和dfs找到连通子块,再利用(xd-xu+1)*(yr-yl+1)是否等于小方块个数来判断这个连通子块是否是长方形

#include<bits/stdc++.h>
using namespace std;
#define int long long
int vis[1005][1005];
char a[1005][1005];
int nextmove[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//右下左上
int n,m;
int xu,xd,yr,yl;
int cnt;
void dfs(int x,int y)
{
    if(x<1||x>n||y<1|y>m||a[x][y]=='*'||vis[x][y])
    return;
    vis[x][y]=1;
    xu=min(x,xu);xd=max(x,xd);
    yl=min(y,yl);yr=max(y,yr);
    cnt++;
    for(int i=0;i<4;i++)
    {
        int tx=x+nextmove[i][0];
        int ty=y+nextmove[i][1];
        dfs(tx,ty);
    }
}
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(!vis[i][j])
            {
                cnt=0;
                xu=yl=10005;
                xd=yr=-1;
                dfs(i,j);
                if((xd-xu+1)*(yr-yl+1)==cnt)
                ans++;
            }
        }
    }
    cout<<ans;
    return 0;
}

E.可口蛋糕

题意:在连续区间中w的和大于饱腹值W的前提下使d的和最大(w恒大于0)之间

思路:先求w和d的前缀和,遍历每个左端点,利用upper_bound找到第一个w的和大于flag的元素,再从后往前直到这个元素,找到d的和的最大值

因为左端点不变,故只需找到pred最大的右端点,因此可预先求一个sign数组来预存i到n之间最大的pred[j],取所有情况的最大值。

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
  int n,flag;
  cin>>n>>flag;
  vector<int>w(n+1);
  vector<int>d(n+1);
  vector<int>prew(n+1);
  vector<int>pred(n+1);
  vector<int>sign(n+5);
  for(int i=1;i<=n;i++)
  {
     cin>>w[i];
	 prew[i]=prew[i-1]+w[i];	
  } 
  for(int i=1;i<=n;i++)
  {
  	cin>>d[i];
  	pred[i]=pred[i-1]+d[i];
  }
  sign[n]=pred[n];
  for(int i=n-1;i>=1;i--)
  {
  	sign[i]=max(sign[i+1],pred[i]);
  }
  int sum=-1000000000000000000;
  for(int i=1;i<=n;i++)
  {
  	auto it=upper_bound(prew.begin()+i,prew.end(),flag+prew[i-1]);
  	if(it!=prew.end())
  	{
  	int t=it-prew.begin();
  	sum=max(sum,sign[t]-pred[i-1]);
  	//cout<<"signt-predt=="<<sign[t]<<"-"<<pred[i-1]<<"t=="<<t<<"\n";
   }
  }
  cout<<sum<<"\n";
  return 0;
}

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值