Codeforse Round #634(div3)解题报告(A-E2)

第一次达成度这么高(虽然是div3的比赛),相信以后会更好!
提交传送门
在这里插入图片描述A.Candies and Two Sisiters
在这里插入图片描述
在这里插入图片描述
题目大意:实实在在的水题,给你一个数n,你需要找出两个数a,b使a+b=n,但条件是1.a>b,2.a>0且b>0
输出这样子的a,b有多少对

思路:直接二半分(n-1)/2.

#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
 
int main(void)
{
    ll t,n,a,b,c=0;
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld",&n);
        printf("%lld\n",(n-1)/2);
    }
}

B. Construct the String
在这里插入图片描述题目大意:题目给你三个数:n,a,b,你的任务是:构成一个长度为n的(只有26个小写字母)字符串,该字符串的约束条件:在一连续长度为a的子串中有b个不同类型的字符。最后输出这个字符串(答案不唯一)
思路:简简单单,就先看b是多少,然后每次顺序输出(a,b…z)这样子的连续串,长度为b,记住字符串长度不能超过n。(压根与a是多少毫无关系)
在这里插入图片描述
这就是一个n长度的串——abcabca,可以看出每长度为5的子串都有3个不同类型的字符。

#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
 
int main()
{
    ll t,n,a,b,w;
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld%lld%lld",&n,&a,&b);
        while(n)
        {
            for(int i=0;i<b&&n>0;i++)
            {
                printf("%c",'a'+i);
                n--;
            }
        }
        cout<<endl;
    }
    return 0;
}

C. Two Teams Composing
C题(二分+贪心算法+排序)?-?
在这里插入图片描述
在这里插入图片描述题目大意:给你一个元素个数为n的数组,你的任务是将这个数组分成两个元素数量都为 x 的子数组A,B,对于A数组,其元素一定全部都是不一样的,对于B数组,其元素一定全部都是一样的,其中A中某些元素可以与B数组的某些元素是一样的,你现在目的是怎样不重复地分配才能使 x 尽可能最大并输出这个最大的 x 。(x+x<=n)
思路:(手动滑稽)我这题是写的最乱的,大家可以看看别人的博客

#include<bits/stdc++.h>
typedef long long int ll;
const int size = 2e5+50;
using namespace std;
ll flag[size],bj[size];
int main()
{
    ll t,n,a[size];
    scanf("%lld",&t);
    while(t--)
    {
        memset(flag,0,sizeof(flag));
        memset(bj,0,sizeof(bj));
        scanf("%lld",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            flag[a[i]]++;
        }
        ll c1=0,c2=0,ma=1;
        for(int i=1;i<=n;i++)
        {
            if(flag[a[i]]==1) c2++;
            else if(flag[a[i]]>1 && bj[a[i]]==0)
            {
                c1++;
                bj[a[i]]=1;
                ma=max(ma,flag[a[i]]);
            }
        }
        if(n==1) cout<<"0"<<endl;
        else
        {
            ll mid = ma;
            if(c1+c2-1>=ma);
            else if(c1+c2<ma) ma=c1+c2;
            else if(c1+c2>=ma-1) ma=min(ma-1,c1+c2);
            printf("%lld\n",ma);
        }
    }
    return 0;
}

D. Anti-Sudoku
D题(构造算法+模拟)
在这里插入图片描述在这里插入图片描述题目大意:给你一个正确的数独,你现在有最多九次改变数独里面数的机会,你的任务是将原来正确的数独经过你的改变后变成了这样子的数独——每行每列每3x3宫格至少有两个相同的数,输出你改变后的数独(答案肯定不唯一)

思路::(十分水的题目,但想了有那么久,脑子还是反应慢了。)做九次下面的变化:
在这里插入图片描述
很清楚看的到,我修改的九个位置都控制着独立的一行,独立的一列,独立的3x3宫格,与其他的改变点互不干扰。

#include<bits/stdc++.h>
typedef long long int ll;
const int size = 2e5+50;
using namespace std;
char sd[11][11];
int jl[11];
 
int main()
{
    ll t,n,a[size];
    scanf("%lld",&t);
    getchar();
    while(t--)
    {
        for(int i=0;i<9;i++)
            gets(sd[i]);
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            {
                if(i==0&&j==0) cout<<(sd[i][j]-'0')%9+1;
                else if(i==1&&j==3) cout<<(sd[i][j]-'0')%9+1;
                else if(i==2&&j==6) cout<<(sd[i][j]-'0')%9+1;
                else if(i==3&&j==1) cout<<(sd[i][j]-'0')%9+1;
                else if(i==4&&j==4) cout<<(sd[i][j]-'0')%9+1;
                else if(i==5&&j==7) cout<<(sd[i][j]-'0')%9+1;
                else if(i==6&&j==2) cout<<(sd[i][j]-'0')%9+1;
                else if(i==7&&j==5) cout<<(sd[i][j]-'0')%9+1;
                else if(i==8&&j==8) cout<<(sd[i][j]-'0')%9+1;
                else cout<<sd[i][j];
            }
            cout<<endl;
        }
    }
    return 0;
}

E2Three Blocks Palindrome (haed version)(前缀数组和+二分+暴力)

E1与E2的题我只讲E2,这个就考察一定的代码功底了,两个题目的意思是一样的,但是E2有点卡空间的感觉,你稍稍开大点数组说不定就会MLE,当然你拿E1的AC代码来交E2大部分情况是TLE的(吐槽一番,我就干过这个傻事)(过了E2一定可以过E1)
在这里插入图片描述
在这里插入图片描述题目大意:给你一个元素个数为n的数组,你可以删除这个数组里面的某些数,但不能全部删除,可以不删除。你的任务是:这个数组经过你的改变后要满足以下条件——数组可以分成三块:
在这里插入图片描述
注意,这个数组不是回文!!!(坑死都不知道)
思路:直接从E2这里出发
1.我们开辟一个数组pos[200010][202],用来存储在第i个位置和第i个位置之前数字j出现的次数之和,记作pos[i][j]。
2.我们再用STL里面的vector开辟202个动态数组 vector ve[202]。用来 记录每个数字出现的位置
3.为什么是202,因为题目说数组内的元素最大是200,为了防止MTL,所以开辟比200大一点点就可以了。
4.接下来看图演示:
(题目输出x+x+y的最大值)
在这里插入图片描述
我把代码贴上来说明一下:

#include<bits/stdc++.h>
using namespace std;
const int size = 2e5+11;
vector<int> ve[202];
int pos[size][202];
 
int main(void)
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int v=0;
        for(int i=1;i<=200;i++) ve[i].clear();
        for(int i=1;i<=n;i++) for(int j=1;j<=200;j++) pos[i][j]=0;
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            v=max(v,x);
            for(int j=1;j<=v;j++)
                pos[i][j] = pos[i-1][j]+(j==x);
            ve[x].push_back(i);
        }
        int sum=0;
        for(int i=1;i<=v;i++)
        {
            int l=0,r=ve[i].size()-1;
            sum=max(sum,r+1);//这是为了保证最小的目标串长度
            //因为每个ve都可以组成一个长度为ve[i].size()的目标串
            //我们下面的代码只是寻找有没有比这个更长的,有就更换。
            while(l<r)
            {
                int mid=0;
                int right = ve[i][r];
                //i这个数出现在题目数组最远的位置是right
                int left = ve[i][l];
                //i这个数出现在题目数组最近的位置是left
                for(int j=1;j<=v;j++)
                    mid=max(mid,pos[right-1][j]-pos[left][j]);
                //这个mid是为了求最近的i和最远的i之间存在的最大的y
                //y就是上面题目大意讲解的那个y,为什么肯定这个y就一定
                //有y个相同的数,而且是夹在i左右之间,因为这个pos数组
                //求的是j这个数在i左右位置出现的次数,那肯定都是一类
                //相同的数。
                sum=max(sum,mid+2*(l+1));
                //这个mid+2*(l+1)就是你求出来的x+x+y的值,mid的看作y,
                //l+1看作是x,这个循环能进行的次数越多,代表ve[i]这个
                //size就越大。
                l++,r--;
            }
        }
        printf("%d\n",sum);
    }
}

最后一题好好理解,我讲的可能模棱两可,凡事还得靠自己,加油!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌晨小街

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值