题意:剪纸中'.'连接成的长方形的个数(正方形是特殊的长方形)
思路:利用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;
}
题意:在连续区间中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;
}