题目 |
T1 |
T2 |
T3 |
T4 |
当前分数 |
\(\color{#00CC00}100\) |
\(\color{#E68A00}30\) |
\(\color{#00CC00}100\) |
\(\color{red}0\) |
T2 调了 1h 没调出来,丢了一坨没分的shi扔了。
我想放一下作为开头:
include <bits/stdc++.h> #define int long long using namespace std; inline int read() { int w=1,s=0;char ch=getchar(); while(!isdigit(ch)){if(ch'-')w=-1;ch=getchar();} while(isdigit(ch)){s=s10+(ch-'0');ch=getchar();} return ws; } const int mod=998244353; const int maxn=3e3+10; const int inf=1e9+7; int n,m; char a[maxn][maxn]; bool hang[maxn],lie[maxn]; bool f[maxn][maxn]; map<string,int> mp; int dfs() { bool can=1; for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(!f[i][j]){can=0;break;} if(can){return 0;} string s; for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) { if(f[i][j])s=s+'W'; else s=s+a[i][j]; } if(mp[s])return mp[s]; vector hangr,hangb,lier,lieb; for(int i=1;i<=n;i++) { if(hang[i])continue; bool r=1; for(int j=1;j<=m;j++)if(a[i][j]'B'&&!f[i][j]){r=0;break;} if(r)hangr.push_back(i); } for(int i=1;i<=n;i++) { if(hang[i])continue; bool b=1; for(int j=1;j<=m;j++)if(a[i][j]'R'&&!f[i][j]){b=0;break;} if(b)hangb.push_back(i); } for(int i=1;i<=m;i++) { if(lie[i])continue; bool r=1; for(int j=1;j<=n;j++)if(a[j][i]'B'&&!f[j][i]){r=0;break;} if(r)lier.push_back(i); } for(int i=1;i<=m;i++) { if(lie[i])continue; bool b=1; for(int j=1;j<=n;j++)if(a[j][i]'R'&&!f[j][i]){b=0;break;} if(b)lieb.push_back(i); } int res=inf; for(auto i : hangr) { for(int j=1;j<=m;j++) { f[i][j]=1; } hang[i]=1; res=min(res,dfs()+1); for(int j=1;j<=m;j++) { f[i][j]=0; } hang[i]=0; } for(auto i : hangb) { for(int j=1;j<=m;j++) { f[i][j]=1; } hang[i]=1; res=min(res,dfs()+1); for(int j=1;j<=m;j++) { f[i][j]=0; } hang[i]=0; } for(auto i : lier) { for(int j=1;j<=n;j++) { f[j][i]=1; } lie[i]=1; res=min(res,dfs()+1); for(int j=1;j<=n;j++) { f[j][i]=0; } lie[i]=0; } for(auto i : lieb) { for(int j=1;j<=n;j++) { f[j][i]=1; } lie[i]=1; res=min(res,dfs()+1); for(int j=1;j<=n;j++) { f[j][i]=0; } lie[i]=0; } return mp[s]=res; } void Sub1() { int ans=inf; mp.clear(); for(int i=1;i<=n;i++)hang[i]=0; for(int j=1;j<=m;j++)lie[j]=0; for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)f[i][j]=0; ans=dfs(); printf("%lld\n",(ansinf?-1:ans)); } void Main() { n=read(),m=read(); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cin>>a[i][j]; } } bool f=0; for(int i=1;i<=n;i++){bool ff=1;for(int j=2;j<=m;j++)if(a[i][j]!=a[i][j-1]){ff=0;break;}if(ff)f=1;break;} for(int i=2;i<=m;i++){bool ff=1;for(int j=1;j<=n;j++)if(a[j][i]!=a[j][i-1]){ff=0;break;}if(ff)f=1;break;} if(!f){puts("-1");return ;} Sub1(); } signed main() { #ifdef Lydic freopen(".in", "r", stdin); freopen(".out", "w", stdout); // #else // freopen("mst.in", "r", stdin); // freopen("mst.out", "w", stdout); #endif int T=read(); while(T--)Main(); return 0; }
好了,开始写总结。
赛时
开题,先看 T1。
暴力一开始写挂了,所以直接去想正解(因为这时候一车人过了)。
简单思考发现最终相等的值是唯一的,所以容易想到去构造一中最少的修改方案。
有一种线性的贪心构造,写完以后发现过了大样例,但是想到之前大样例全过但是真实数据一分没有的经历,我弱弱的放弃了。
舍弃一下正解,胡一个稳定 \(\mathcal{O}(n^2)\) 的 DP,胡完以后看看提交记录,发现 AKIG 叕 AK 了,我大惊。
写出来以后发现没挂,于是开始考虑用什么数据结构去优化。
但是我赛时一直傻傻地盯着 DP 的内层循环去找数据结构优化,丝毫没发现我刚刚的贪心是正解。
到最后也没出来,然后最终得分 60pts。
T2 的话看不出来什么东西,想先写一下暴力,然后就有了上面的一大坨东西。
T3 的话感觉是一个很可做的数据结构计数问题,暴力思路很好想,然后纸上推推画画,随便用树状数组优化一下,就莫名其妙地过掉了大样例。赛时感觉比 T1 简单。(我猜某鸡不会看这篇文章,所以在这里口嗨一下它的 T3:\(\Large \color{red}{菜}\))
T4 看了一眼,感觉 T2 的分可以拿到,所以决定死盯 T2,然后到最后也没盯出来,使得最基本的暴力分数也没拿到。
赛后
发现我是为数不多过 T3 但是没过 T1 的人,我太菜了。
一听别人的思路就会 T1 了,花了不到 5min 就过了。我更菜了。
现在在订 T2,努力在下个国庆节日期是完全平方数之前订出来(3026.10.01)。
最近的比赛时间不够的问题逐渐显现出来,可能是赛时写的不够勤,没做到有分就写。
导致我最后 20min 键盘都快敲出火了。
写完了,溜了。