就写了两个题,以为要掉分,结果早上起来发现还上分了(说明wtcl
A - Rainbow Dash, Fluttershy and Chess Coloring
无论边长是奇数还是偶数,考虑每次操作最外层的一圈,一个人操作一圈的一般,然后另一个人就能够把这一圈涂满,而且还能继续操作最外圈。每次2人操作后问题变成边长-2的情况。稍微思考一下就可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int main()
{IO;int T;cin>>T;while(T--){cin>>n;if(n&1)cout<<(n-3)/2+2<<endl;elsecout<<(n-2)/2+2<<endl;}return 0;
}
B - Applejack and Storages
统计4的倍数和2的倍数。其中既是4的倍速也是2的倍数只看做4的倍数。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100010;
int mp[N];
int n,q;
int main()
{IO;cin>>n;int x=0,y=0;for(int i=1;i<=n;i++){int a;cin>>a;mp[a]++;if(mp[a]%2==0) y++;//加完后是2的倍数if(mp[a]%4==0) x++,y-=2; //加完后是4的倍数(要把二的倍数减去)}cin>>q;while(q--){char op;int a;cin>>op>>a;if(op=='+'){mp[a]++;if(mp[a]%2==0) y++;if(mp[a]%4==0) x++,y-=2;}else{if(mp[a]%2==0) y--;//减之前是2的倍数 2的倍数减小一个if(mp[a]%4==0) x--,y+=2;//减之前是4的倍数 4的倍数减小一个,2的倍数最终应该增加一个(由于上面减了一个要加二个这点wa了2发)mp[a]--;}if(x>=1&&y>=2||x>=2) cout<<"YES"<<endl;else cout<<"NO"<<endl;}return 0;
}
C - Pinkie Pie Eats Patty-cakes
最小距离最大?二分?,做题的时候我就发现二分的check函数好像不容易写。如果能够写出check函数其实好像不用二分直接答案就出来了。
果不其然,群友说这就是个贪心题,后来想了想果然是。1111222233334445566789
比如上述序列,构造方式如下:
1234569
123457
123468
123
如果是11111222233334445566789
123469
12346
12357
12458
13
因此有以下贪心
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100010;
int mp[N],n;
int main()
{IO;int T;cin>>T;while(T--){cin>>n;int mx=0;memset(mp,0,sizeof mp);for(int i=1;i<=n;i++){int a;cin>>a;mp[a]++;mx=max(mx,mp[a]);}int cnt=0;for(int i=0;i<N;i++)if(mp[i]==mx) cnt++;cout<<cnt+(n-cnt*mx)/(mx-1)-1<<endl;}return 0;
}
D-Rarity and New Dress
悬线dp?第一次听说,一定要把这题补了
解法一:二分抄代码题解
维护菱形中间点,先求上下最长,维护左右最长(不能超过上下最长)
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#define debug(x) cout<<#x<<": "<<x<<" "
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2010;
int n,m;
ll ans;
int u[N][N],d[N][N],l[N][N],r[N][N];
int h[N][N];
char s[N][N];
int main()
{IO;cin>>n>>m;for(int i=1;i<=n;i++) cin>>s[i]+1;// 预处理for(int j=1;j<=m;j++){for(int i=1;i<=n;i++){if(s[i][j]==s[i-1][j]) u[i][j]=u[i-1][j]+1;else u[i][j]=1;}for(int i=n;i;i--){if(s[i][j]==s[i+1][j]) d[i][j]=d[i+1][j]+1;else d[i][j]=1;}for(int i=1;i<=n;i++) h[i][j]=min(d[i][j],u[i][j]);}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(s[i][j]==s[i][j-1]) l[i][j]=min(l[i][j-1]+1,h[i][j]);else l[i][j]=1;}for(int j=m;j;j--){if(s[i][j]==s[i][j+1]) r[i][j]=min(r[i][j+1]+1,h[i][j]);else r[i][j]=1;}}// 求答案for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)ans+=min(l[i][j],r[i][j]);cout<<ans<<endl;return 0;
}
解法二:
这个菱形可以看成4个等腰直角三角形,维护等腰直角三角形(即菱形中心点)
f[i][j]
表示s[i][j]
为直角顶点最大等腰直角三角形。4次dp
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#define debug(x) cout<<#x<<": "<<x<<" "
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2010;
int n,m;
ll ans;
int f1[N][N],f2[N][N],f3[N][N],f4[N][N];
char s[N][N];
int main()
{IO;cin>>n>>m;for(int i=1;i<=n;i++) cin>>s[i]+1;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){f1[i][j]=1;if(s[i][j]==s[i-1][j]&&s[i][j]==s[i][j-1]) f1[i][j]=min(f1[i-1][j],f1[i][j-1])+1;}for(int i=1;i<=n;i++)for(int j=m;j;j--){f2[i][j]=1;if(s[i][j]==s[i-1][j]&&s[i][j]==s[i][j+1]) f2[i][j]=min(f2[i-1][j],f2[i][j+1])+1;}for(int i=n;i;i--)for(int j=1;j<=m;j++){f3[i][j]=1;if(s[i][j]==s[i+1][j]&&s[i][j]==s[i][j-1]) f3[i][j]=min(f3[i+1][j],f3[i][j-1])+1;}for(int i=n;i;i--)for(int j=m;j;j--){f4[i][j]=1;if(s[i][j]==s[i+1][j]&&s[i][j]==s[i][j+1]) f4[i][j]=min(f4[i+1][j],f4[i][j+1])+1;}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) ans+=min(min(f1[i][j],f2[i][j]),min(f3[i][j],f4[i][j]));cout<<ans<<endl;return 0;
}