就写了两个题,以为要掉分,结果早上起来发现还上分了(说明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;
else
cout<<(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;
}
来源:oschina
链接:https://my.oschina.net/u/4284005/blog/4482042