| 题目 | 难度 | 知识点 |
|---|---|---|
| A 小红的环形字符串 | ★ | 签到/暴力枚举 |
| B 相邻不同数字的标记 | ★ | 线性DP |
| C 小红的俄罗斯方块 | ★★ | 模拟 |
| D 小红打怪 | ★★ | 二分+前缀和 |
非常开心的一次AK,考察的知识点是我会的,我也都做出来了。
A签到,B简单的DP,C模拟,D二分注意计算单个怪需要的血量这个分情况讨论计算一下。
总结,打之前一定要睡觉+洗脸让脑袋冷静一下。
小红的环形字符串
#include<bits/stdc++.h>
using namespace std;
string a,b;
int cnt;
int main(void)
{
cin>>a>>b;
a=a+a;
for(int i=0;i<a.size()/2;i++)
{
string c=a.substr(i,b.size());
if(c==b) cnt++;
}
cout<<cnt;
return 0;
}
相邻不同数字的标记
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
typedef long long int LL;
LL dp[N],n,a[N];
string s;
int main(void)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
cin>>s;
s="1"+s;
for(int i=1;i<=n;i++)
{
dp[i]=dp[i-1];
if( s[i]!=s[i-1] && s[i-1]!='1' )
dp[i]=max(dp[i],dp[i-2]+a[i]+a[i-1]);
}
cout<<dp[n];
return 0;
}
小红的俄罗斯方块
模拟,想的是1000x8的网格,从下往上模拟,找到可以放置的位置,且需要比对应列最小的位置要大(即必须在之前放过的方框上边)
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
typedef long long int LL;
int st[N][N],n,maxv[N];
bool check(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)
{
if(st[x1][y1]) return false;
if(st[x2][y2]) return false;
if(st[x3][y3]) return false;
if(st[x4][y4]) return false;
if(x1>=maxv[y1]) return false;
if(x2>=maxv[y2]) return false;
if(x3>=maxv[y3]) return false;
if(x4>=maxv[y4]) return false;
return true;
}
void get(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)
{
st[x1][y1]=1;
st[x2][y2]=1;
st[x3][y3]=1;
st[x4][y4]=1;
}
int main(void)
{
cin>>n;
for(int i=1;i<=8;i++) maxv[i]=1e3+10;
while(n--)
{
int op,l; cin>>op>>l;
if(op==0)
{
int x1=1000,y1=l;
int x2=999,y2=l;
int x3=998,y3=l;
int x4=1000,y4=l+1;
while( !check(x1,y1,x2,y2,x3,y3,x4,y4) ) x1--,x2--,x3--,x4--;
maxv[l]=x3,maxv[l+1]=x4;
get(x1,y1,x2,y2,x3,y3,x4,y4);
}else if(op==90)
{
int x1=1000,y1=l;
int x2=999,y2=l;
int x3=999,y3=l+1;
int x4=999,y4=l+2;
while( !check(x1,y1,x2,y2,x3,y3,x4,y4) ) x1--,x2--,x3--,x4--;
maxv[l]=x2,maxv[l+1]=x3,maxv[l+2]=x4;
get(x1,y1,x2,y2,x3,y3,x4,y4);
}else if(op==180)
{
int x1=998,y1=l;
int x2=998,y2=l+1;
int x3=999,y3=l+1;
int x4=1000,y4=l+1;
while( !check(x1,y1,x2,y2,x3,y3,x4,y4) ) x1--,x2--,x3--,x4--;
maxv[l]=x1,maxv[l+1]=x2;
get(x1,y1,x2,y2,x3,y3,x4,y4);
}else if(op==270)
{
int x1=1000,y1=l;
int x2=1000,y2=l+1;
int x3=1000,y3=l+2;
int x4=999,y4=l+2;
while( !check(x1,y1,x2,y2,x3,y3,x4,y4) ) x1--,x2--,x3--,x4--;
maxv[l]=x1,maxv[l+1]=x2,maxv[l+2]=x4;
get(x1,y1,x2,y2,x3,y3,x4,y4);
}
}
for(int i=1;i<=8;i++)
{
int j=0;
while(j+1<=1000 && st[j+1][i]==0 ) j++;
cout<<1000-j<<" ";
}
return 0;
}
其实我们是不是可以直接存每一个列的最高位置,对应不同的情况考虑更新后的最高情况。
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int h[15],n;
int main(void)
{
cin>>n;
while(n--)
{
int op,l; cin>>op>>l;
if(op==0){//1
int maxv=max(h[l],h[l+1]);
h[l]=maxv+3,h[l+1]=maxv+1;
}else if(op==90)//2
{
if(h[l+1]>h[l] || h[l+2]>h[l])
{
int maxv=max(h[l+1],h[l+2]);
h[l]=maxv+1,h[l+1]=maxv+1,h[l+2]=maxv+1;
}else
{
int maxv=h[l];
h[l]=maxv+2,h[l+1]=maxv+2,h[l+2]=maxv+2;
}
}else if(op==180)
{
if(h[l+1]>=h[l])
{
int maxv=h[l+1];
h[l]=maxv+3,h[l+1]=maxv+3;
}else{
int maxv=h[l+1]+3;
maxv=max(maxv,h[l]+1);
h[l]=maxv,h[l+1]=maxv;
}
}else if(op==270)//4
{
int maxv=max({h[l],h[l+1],h[l+2]});
h[l]=maxv+1,h[l+1]=maxv+1,h[l+2]=maxv+2;
}
}
for(int i=1;i<=8;i++) cout<<h[i]<<" ";
return 0;
}
小红打怪
比较裸的二分,需要注意一些细节。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
typedef long long int LL;
int n,h,k;
LL a[N],b[N],ans[N],m;
int main(void)
{
cin>>n>>h>>k;
for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
for(int i=1;i<=n;i++)
{
LL cnt=a[i]/4;
if(cnt==0)
{
if(a[i]<=2) ans[i]=0;
else if(a[i]==3) ans[i]=1;
}
else
{
LL temp=a[i]%4;
LL sum=cnt*3-1;
if(temp<=2 && temp) sum++;
else if(temp==3) sum+=2;
ans[i]=sum;
}
ans[i]=ans[i]*b[i];
}
sort(ans+1,ans+n+1);
for(int i=1;i<=n;i++) ans[i]=ans[i]+ans[i-1];
cin>>m;
while(m--)
{
LL x; cin>>x;
LL sum=h+x*k;
int l=0,r=n;
while(l<r)
{
int mid=(l+r+1)/2;
if(ans[mid]<sum) l=mid;
else r=mid-1;
}
cout<<l<<" ";
}
return 0;
}