初三奥赛模拟测试3
初三奥赛模拟测试3
\(T1'\) 糖果 \(100pts\)
\(T2'\) 魔法仪式 \(0pts\)
\(T3'\) 独特的数组 \(0pts\)
\(T4'\) 约会 \(0pts\)
\(T1\) 网格图 \(0pts\)
- 正解
-
先处理出所有连通块及其大小,并记录每个
.
在哪个连通块中。 -
考虑枚举 \(k \times k\) 的正方形,将正方形内的所有
.
,在其对应的连通块大小中扣除,然后再枚举正方形外圈的连通块,求它们的大小之和,取 \(\max\) 即可。 -
记其右下角为 \((x,y)\) 。考虑右下角由 \((x,y-1)\) 变成 \((x,y)\) 时, \((i,y-k+1-1)\) 无法对答案产生贡献, \((i,y)\) 会对答案产生贡献,故可以只枚举这两列从而优化时间复制度。
-
注意及时消除影响。
点击查看代码
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1},num[250010],pos[510][510],vis[510][510],viss[250010]; char c[510][510]; void dfs(int x,int y,int n,int id) { vis[x][y]=1; num[id]++; pos[x][y]=id; for(int i=0;i<=3;i++) { if(1<=x+dx[i]&&x+dx[i]<=n&&1<=y+dy[i]&&y+dy[i]<=n&&vis[x+dx[i]][y+dy[i]]==0) { dfs(x+dx[i],y+dy[i],n,id); } } } int main() { int n,m,id=0,sum,ans=0,i,j,k,h; cin>>n>>m; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { cin>>c[i][j]; vis[i][j]=(c[i][j]=='X'); } } for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(vis[i][j]==0) { id++; dfs(i,j,n,id); } } } for(i=m;i<=n;i++) { for(j=m;j<=n;j++) { if(j==m) { for(k=i-m+1;k<=i;k++) { for(h=j-m+1;h<=j;h++) { if(c[k][h]=='.') { num[pos[k][h]]--; } } } } else { for(k=i-m+1;k<=i;k++) { h=j-m+1-1; if(c[k][h]=='.') { num[pos[k][h]]++; } } for(k=i-m+1;k<=i;k++) { h=j; if(c[k][h]=='.') { num[pos[k][h]]--; } } } sum=0; if(1<=i-m+1-1) { for(k=j-m+1;k<=j;k++) { sum+=(viss[pos[i-m+1-1][k]]==0)*num[pos[i-m+1-1][k]]; viss[pos[i-m+1-1][k]]=1; } } if(i+1<=n) { for(k=j-m+1;k<=j;k++) { sum+=(viss[pos[i+1][k]]==0)*num[pos[i+1][k]]; viss[pos[i+1][k]]=1; } } if(1<=j-m+1-1) { for(k=i-m+1;k<=i;k++) { sum+=(viss[pos[k][j-m+1-1]]==0)*num[pos[k][j-m+1-1]]; viss[pos[k][j-m+1-1]]=1; } } if(j+1<=n) { for(k=i-m+1;k<=i;k++) { sum+=(viss[pos[k][j+1]]==0)*num[pos[k][j+1]]; viss[pos[k][j+1]]=1; } } if(1<=i-m+1-1) { for(k=j-m+1;k<=j;k++) { viss[pos[i-m+1-1][k]]=0; } } if(i+1<=n) { for(k=j-m+1;k<=j;k++) { viss[pos[i+1][k]]=0; } } if(1<=j-m+1-1) { for(k=i-m+1;k<=i;k++) { viss[pos[k][j-m+1-1]]=0; } } if(j+1<=n) { for(k=i-m+1;k<=i;k++) { viss[pos[k][j+1]]=0; } } if(j==n) { for(k=i-m+1;k<=i;k++) { for(h=j-m+1;h<=j;h++) { if(c[k][h]=='.') { num[pos[k][h]]++; } } } } ans=max(ans,sum+m*m); } } cout<<ans<<endl; return 0; }
-
\(T2\) 序列问题 \(0pts\)
- 正解
-
设 \(f_{i}\) 表示处理到第 \(i\) 个数且处理后的序列以 \(a_{i}\) 结尾,且 \(a_{i}\) 产生了贡献时的最大值,状态转移方程为 \(f_{i}= \max\limits_{j=1}^{i-1} \{ [a_{j}<a_{i} \And \And a_{i}-a_{j} \le i-j] \times (f_{j}+1) \}= \max\limits_{j=1}^{n} \{ [a_{j}<a_{i} \And \And j-a_{j} \le i-a_{i}] \times (f_{j}+1) \}\) 。
-
维护 \(i-a_{i}\) 的最长不降子序列即可。
点击查看代码
struct node { int x,id; }a[500010]; bool cmp(node a,node b) { return (a.x==b.x)?(a.id>b.id):(a.x<b.x);//注意当x相等时,id要降序排序 } int f[500010]; int main() { freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); int n,ans=0,i; cin>>n; for(i=1;i<=n;i++) { cin>>a[i].x; a[i].id=i; } sort(a+1,a+1+n,cmp); for(i=1;i<=n;i++) { if(a[i].id-a[i].x>=0) { if(a[i].id-a[i].x>=f[ans]) { ans++; f[ans]=a[i].id-a[i].x; } else { f[upper_bound(f+1,f+1+ans,a[i].id-a[i].x)-f]=a[i].id-a[i].x; } } } cout<<ans<<endl; fclose(stdin); fclose(stdout); return 0; }
-
\(T3\) 置换 \(0pts\)
-
原题: BZOJ4673 置换
-
What is 置换 ?
点击查看官方题解
\(T4\) 同桌的你 \(0pts\)
-
原题: BZOJ4203 同桌的你
-
正解
点击查看官方题解
总结
后记
- 因 \(T1' \sim T4'\) 机房大部分人都写过, @Pursuing_OIer 和 \(huge\) 说了, \(huge\) 又和 \(miaomiao\) 说,所以把题换成了 \(T1 \sim T4\) 。
- 东拼西凑的题目来源
- \(T1' \sim T4'\) 来自 AcCoders 2023年多校联训NOIP层测试5 。
- \(T1,T2\) 来自 2019.10.1 长乐一中陈煜翔 NOIP2019 模拟赛 day 1(A组) T1,T2 。
- \(T3\) 来自 2016.7.6 Yang Jiaqi NOI2016 模拟赛 T3 。
- \(T4\) 来自 2020.1.30 省选模拟13 。
- \(miaomiao\) 把 \(T1,T2\) 官方题解放在了
solution.pptx
里,把 \(T3\) 题面放在了置换.pdf
里,把 \(T3\) 官方题解放在了solution.pdf
里,把 \(T4\) 官方题解放在了deskmate.pdf
里。 - \(T1\) 为标准输入输出, \(T3 \sim T4\) 为文件输入输出。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18096929,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。