牛客小白月赛34题解

比赛链接

19点02分时发现比赛开始了,在纠结要不要打,如果打的话就亏了(狗头 过了一个小时上去看看,还是打了打hhh 除了G题没怎么看过。。
先放代码,之后再补题解和简单的题意hhh

Add爱科学1.0

每次可以选择一个字符修改为另一个字符,使得最终字符串呈递增排序。
动态规划
对于当前字符si,dp当前字符变为A~Z需要的最小花费

int n,dp[30],mi[30];
char s[maxn];
void solve()
{
    sd(n);
    sc(s+1);
    rep(i,1,n)
    {
        rep(j,0,25)
        {
            if(j!=s[i]-'A')dp[j]=mi[j]+1;
            else dp[j]=mi[j];
            if(!j)mi[j]=dp[j];
            else mi[j]=min(mi[j-1],dp[j]);
        }
    }
    pd(mi[25]);
}

B dd爱探险

/*
状压dp嚯
*/
int n,p[20][20];
int sum[maxn][20][4],ans;
void solve()
{
    memset(sum,INF,sizeof sum);
    sd(n);
    rep(i,1,n)rep(j,1,n)sd(p[i][j]);
    rep(i,1,n)sum[(1<<(i-1))][i][0]=0;
    rep(i,1,(1<<n)-1)
    {
        rep(j,1,n)//准备去往的下一个点
        {
            if(!(i&(1<<(j-1))))continue;
            rep(k,1,n)//前一个点
            {
                if(!(i&(1<<(k-1)))||k==j)continue;
                sum[i][j][0]=min(sum[i][j][0],sum[i^(1<<(j-1))][k][0]+p[k][j]);
                sum[i][j][1]=min(sum[i][j][1],sum[i^(1<<(j-1))][k][0]);
                sum[i][j][1]=min(sum[i][j][1],sum[i^(1<<(j-1))][k][1]+p[k][j]);
                sum[i][j][2]=min(sum[i][j][2],sum[i^(1<<(j-1))][k][0]+p[k][j]*2);
                sum[i][j][2]=min(sum[i][j][2],sum[i^(1<<(j-1))][k][2]+p[k][j]);
                sum[i][j][3]=min(sum[i][j][3],sum[i^(1<<(j-1))][k][3]+p[k][j]);
                sum[i][j][3]=min(sum[i][j][3],sum[i^(1<<(j-1))][k][2]);
                sum[i][j][3]=min(sum[i][j][3],sum[i^(1<<(j-1))][k][1]+p[k][j]*2);
            }
        }
    }
    ans=1e9;
    rep(i,1,n)ans=min(ans,sum[(1<<n)-1][i][3]);
    pd(ans);
}

C dd爱科学2.0

int n,dp[30],mi[30];
char s[maxn];
void solve()
{
    sd(n);
    sc(s+1);
    rep(i,1,n)
    {
        rep(j,0,25)
        {
            dp[j]=mi[j]+abs(s[i]-'A'-j);
            if(!j)mi[j]=dp[j];
            else mi[j]=min(mi[j-1],dp[j]);
        }
    }
    pd(mi[25]);
}

D dd爱矩阵

给一个n*n矩阵,从每行选一个数,共n^n种结果,要求输出前n大的和。
(输出结果得从大到小排序。。。
对于第i行,从前i-1行得到的前n大和求和,每次只要求n大的和。

int n,a[maxn][maxn];
int sum[maxn];
priority_queue<int,deque<int>,greater<int> >pq;
void solve()
{
    sd(n);
    rep(i,1,n)rep(j,1,n)sd(a[i][j]);
    rep(i,1,n)sum[i]=a[1][i];
    sort(sum+1,sum+1+n);
    rep(i,2,n)
    {
        sort(a[i]+1,a[i]+1+n);
        dep(j,n,1)dep(k,n,1)
        {
            if(pq.size()>=n&&sum[j]+a[i][k]<pq.top())break;
            pq.push(sum[j]+a[i][k]);
            while(pq.size()>n)pq.pop();
        }
        rep(j,1,n)sum[j]=pq.top(),pq.pop();
    }
    dep(i,n,1)pdk(sum[i]);
    puts("");
}

E dd爱旋转

第一种操作的结果:矩阵上下翻转,左右翻转。
第二种操作的结果:矩阵上下翻转。

int n,a[maxn][maxn];
int cnt1,cnt2;
void solve()
{
    sd(n);
    rep(i,1,n)rep(j,1,n)sd(a[i][j]);
    int q;
    sd(q);
    while(q--)
    {
        int x;
        sd(x);
        if(x==1)cnt1^=1,cnt2^=1;
        else cnt2^=1;
    }
    if(cnt1)
    {
        rep(i,1,n)
        {
            rep(j,1,n/2)swap(a[i][j],a[i][n-j+1]);
        }
    }
    if(cnt2)
    {
        dep(i,n,1)
        {
            rep(j,1,n)pdk(a[i][j]);
            puts("");
        }
    }
    else
    {
        rep(i,1,n)
        {
            rep(j,1,n)pdk(a[i][j]);
            puts("");
        }
    }
}

F dd爱框框

给一个长度为n的数组,要求找到最小的区间[l,r],区间内的和大于等于x,输出最小的l和r。
二分长度

int n,x,a[maxn];
int ansl,ansr;
bool check(int len)
{
    ll sum=0;
    rep(i,1,len)sum+=a[i];
    if(sum>=x)
    {
        ansl=1;ansr=len;
        return 1;
    }
    rep(i,len+1,n)
    {
        sum-=a[i-len];
        sum+=a[i];
        if(sum>=x)
        {
            ansl=i-len+1;
            ansr=i;
            return 1;
        }
    }
    return 0;
}
void solve()
{
    sdd(n,x);
    rep(i,1,n)sd(a[i]);
    int l=1,r=n;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid))r=mid-1;
        else l=mid+1;
    }
    pdd(ansl,ansr);
}

H dd爱整齐

k有限序列:
k=3时:…abbbabbbabbba…
每k+1个一队

/*
一开始还以为k没给呢qwq
*/
int n,k,c,mi,M[maxn],cnt[maxn];
ll sum[maxn],ans,SUM;
void solve()
{
    mi=2e9;
    ans=1e18;
    sdd(n,k);k++;
    rep(i,0,k)M[i]=2e9;
    rep(i,1,n)
    {
        sd(c);
        SUM+=c;
        mi=min(mi,c);
        sum[i%k]+=c;
        M[i%k]=min(M[i%k],c);
        cnt[i%k]++;
    }
    rep(i,0,k-1)
    {
        ll tmp=(SUM-sum[i])-1ll*mi*(n-cnt[i]);
        tmp+=sum[i]-1ll*M[i]*cnt[i];
        ans=min(ans,tmp);
    }
    plld(ans);
}

你可能感兴趣的:(ACM)