牛客周赛 Round 2【题解完成】

81 阅读5分钟
题目难度知识点
A 小红的环形字符串签到/暴力枚举
B 相邻不同数字的标记线性DP
C 小红的俄罗斯方块★★模拟
D 小红打怪★★二分+前缀和

image.png

image.png 非常开心的一次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;
}