Preface
补下好久之前打的比赛博客
这场前面都写的挺稳的,然后一到G就降智了没写出来
A - First ABC
签到
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long u64;
typedef pair <int,int> pi;
const int N=105;
int n,t[3]; char s[N];
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i; for (scanf("%d%s",&n,s+1),i=1;i<=n;++i)
{
++t[s[i]-'A'];
if (t[0]&&t[1]&&t[2]) return printf("%d",i),0;
}
return 0;
}
B - Vacation Together
签到
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long u64;
typedef pair <int,int> pi;
const int N=105;
int n,d,c[N],ans; char s[N];
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i,j; for (scanf("%d%d",&n,&d),i=1;i<=d;++i) c[i]=1;
for (i=1;i<=n;++i)
{
for (scanf("%s",s+1),j=1;j<=d;++j) if (s[j]=='x') c[j]=0;
}
int lst=0; for (i=1;i<=d;++i)
if (!c[i]) ans=max(ans,i-lst-1),lst=i;
ans=max(ans,d-lst);
return printf("%d",ans),0;
}
C - Find it!
根据置换环这类的东西我们知道这是一定会成环的,因此直接顺着出边走,记录下已经到达的点即可
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long u64;
typedef pair <int,int> pi;
const int N=200005;
int n,a[N],ans[N],cnt,st,vis[N];
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&a[i]);
for (ans[++cnt]=1,i=a[1],vis[1]=1;i!=1;i=a[i])
{
ans[++cnt]=i; vis[i]=cnt;
if (vis[a[i]]) { st=vis[a[i]]; break; }
}
for (printf("%d\n",cnt-st+1),i=st;i<=cnt;++i) printf("%d ",ans[i]);
return 0;
}
D - Grid Ice Floor
按题意BFS一遍即可
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long u64;
typedef pair <int,int> pi;
const int N=205,dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int n,m; char a[N][N]; queue <pi> q; bool vis[N][N],inque[N][N];
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i,j,k; for (scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%s",a[i]+1);
q.push(pi(2,2)); vis[2][2]=inque[2][2]=1;
while (!q.empty())
{
int x=q.front().fi,y=q.front().se; q.pop();
for (k=0;k<4;++k)
{
int nx=x,ny=y;
while (a[nx][ny]!='#') vis[nx][ny]=1,nx+=dx[k],ny+=dy[k];
nx-=dx[k], ny-=dy[k];
if (!inque[nx][ny]) q.push(pi(nx,ny)),inque[nx][ny]=1;
}
}
int ans=0; for (i=1;i<=n;++i) for (j=1;j<=m;++j) ans+=vis[i][j];
return printf("%d",ans),0;
}
E - Defect-free Squares
可以枚举左上角的点,然后二分最大延申的长度,检验的话用二位前缀和即可
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long u64;
typedef pair <int,int> pi;
const int N=3005,dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int n,m,k,x,y,sum[N][N]; long long ans;
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i,j; for (scanf("%d%d%d",&n,&m,&k),i=1;i<=k;++i) scanf("%d%d",&x,&y),sum[x][y]=1;
for (i=1;i<=n;++i) for (j=1;j<=m;++j) sum[i][j]+=sum[i][j-1];
for (i=1;i<=n;++i) for (j=1;j<=m;++j) sum[i][j]+=sum[i-1][j];
for (i=1;i<=n;++i) for (j=1;j<=m;++j)
{
int l=0,r=min(n-i+1,m-j+1),mid,ret;
auto calc=[&](CI a,CI b,CI c,CI d)
{
if (a>c) return 0; return sum[c][d]-sum[a-1][d]-sum[c][b-1]+sum[a-1][b-1];
};
while (l<=r) if (mid=l+r>>1,calc(i,j,i+mid-1,j+mid-1)==0) ret=mid,l=mid+1; else r=mid-1;
ans+=ret;
}
return printf("%lld",ans),0;
}
F - Yet Another Grid Task
首先不难发现这题由于每一列最上方的那个#
会直接把这一列下方的格子都变黑,因此我们只关心每列最上方的#
的位置,不妨记为\(h_i\)
因此最后合法的矩阵个数可以转化为合法的序列\(\{h_n\}\)的数量,首先不难发现\(h_i\)要大于等于原来每一列最上方的#
同时对于相邻的两列\((i,i+1)\),显然若\(h_i>h_{i+1}+1\),则该状态不合法,因为\(h_i\)会扩散到下一列去
那么就很容易想到一个DP,令\(f_{i,j}\)表示从右往左确定了第\(i\)列,\(h_i=j\)的方案数,转移用前缀和优化一下即可
复杂度\(O(n\times m)\)
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long u64;
typedef pair <int,int> pi;
const int N=2005,mod=998244353;
int n,m,h[N],f[N][N],g[N][N]; char a[N][N];
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i,j; for (scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%s",a[i]+1);
for (i=1;i<=n;++i) for (j=1;j<=m;++j) if (a[i][j]=='#') h[j]=max(h[j],n-i+1);
for (i=0;i<=n;++i) g[m+1][i]=1;
for (i=m;i>=1;--i)
{
for (j=h[i];j<=n;++j) f[i][j]=g[i+1][max(0,j-1)];
for (j=n;j>=0;--j) g[i][j]=(g[i][j+1]+f[i][j])%mod;
}
return printf("%d",g[1][0]),0;
}
G - One More Grid Task
二维的问题乍一看不好想,我们先考虑一维的情况,这是个很经典的问题
我们枚举每个位置\(i\)作为最小值,用单调栈求出它为最小值的区间,由于所有数非负因此最大的那个区间一定是最优的,这样的复杂度为\(O(n)\)
那么对于这道题我们枚举两行作为约束,将每列的最小值拿出来跑单调栈即可,总复杂度\(O(n^3)\)
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<limits.h>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef unsigned long long u64;
typedef pair <int,int> pi;
typedef vector <int> VI;
const int N=305;
int n,m,a[N][N],mi[N][N][N],sum[N][N][N],L[N],R[N],stk[N],top,pfx[N]; LL ans;
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i,j,k; for (scanf("%d%d",&n,&m),i=1;i<=n;++i)
for (j=1;j<=m;++j) scanf("%d",&a[i][j]);
for (k=1;k<=m;++k)
{
for (i=1;i<=n;++i) for (mi[k][i][i]=sum[k][i][i]=a[i][k],j=i+1;j<=n;++j)
mi[k][i][j]=min(mi[k][i][j-1],a[j][k]),sum[k][i][j]=sum[k][i][j-1]+a[j][k];
}
for (j=1;j<=n;++j) for (k=j;k<=n;++k)
{
for (stk[top=0]=0,i=1;i<=m;++i)
{
while (top&&mi[stk[top]][j][k]>mi[i][j][k]) --top;
L[i]=stk[top]; stk[++top]=i;
}
for (stk[top=0]=m+1,i=m;i>=1;--i)
{
while (top&&mi[stk[top]][j][k]>=mi[i][j][k]) --top;
R[i]=stk[top]; stk[++top]=i;
}
for (i=1;i<=m;++i) pfx[i]=pfx[i-1]+sum[i][j][k];
for (i=1;i<=m;++i) ans=max(ans,1LL*mi[i][j][k]*(pfx[R[i]-1]-pfx[L[i]]));
}
return printf("%lld",ans),0;
}
Postscript
接下来就是把一轮剩下的模拟赛补完就完了
- Contest Programming Beginner AtCoder Toyotacontest programming beginner atcoder contest programming securities beginner contest programming beginner registry contest programming beginner keyence contest programming beginner systems beginner atcoder contest 296 beginner atcoder contest 295 beginner atcoder contest abcde beginner atcoder contest 335 beginner atcoder contest 332