练习记录-cf-div2-853-(A-C)

从11月打的只能写两题现在尽量3题了 就在这里慢慢记录下练习吧 看到成长也是学习的动力之一(补题会继续写,但不一定补的来

今日总结:还是只会写简单思维题的菜狗(今天居然是20开始,差点没赶上!

A题


题意:给出一堆数字,可以自由排序,对于大于等于2的前缀和子数组,要使gcd<=长度

我的解法:没看到排序,浪费了好多时间。比较暴力,求出每两个数的gcd,如果没有两个数的gcd<=2 那么条件不成立,相应的,如果有两个数<=2,再gcd一个数只可能更小

所以后续不需要考虑

我的slove函数代码如下 gcd可以使用__gcd吧

 int n;cin>>n;
    int a[200];
    int flag=1;
    int c;
    for(int i=1;i<=n;i++){
    cin>>a[i];
    }
    int mins=inf;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j) continue;
            mins=min(mins,gcd(a[i],a[j]));
        }
    }
    if(mins>2) flag=0;
    if(flag) cout<<"Yes\n";
    else cout<<"No\n";
View Code

 

 

B题

 


题意:你只能执行一次操作:选择一段区间,将内部数字全部取反(可以为0),操作后的字符串能否为回文;

我的解法:选择前后双指针扫一下,遇到不一样的记录,如果不一样的区间有两个以及以上,就是NO

slove函数如下,写的有点乱好像

    int n;cin>>n;
    string s;cin>>s;
    int L=0,R=n-1;
    int flag1=1,flag2=1;//flag1记录是否出现过不同,flag2记录不同区间是否结束 
    while(L<R){
        if(s[L]!=s[R]){
            if(flag1==1) flag1=0;
            else if(flag2==0) {//已经结束过一个区间
                printf("No\n");
                return;
            }
        }
        else if(flag1==0) flag2=0;//结束一个不同的区间
        L++;R--;
    }
    cout<<"Yes\n";
    return;
View Code

 

C题


其实c想了很久,都是n*m的复杂度,但是用屁股想都知道会被卡掉,都要放弃了 一看那么多人过了,还是静下心写吧。

题意:题目提供一个初始数组,无重复,接下来进行m次操作,输入整数a和b,把a位的数字替换成b,初始数组记为A0,后续每次操作记为A1~Am,

要求从A0~Am中每两个进行组合,拼成的新的数组中,不同数的数量的和(可以看样例解释理解)

我的解法:首先,我的计算方法是,从A1开始,每个往前遍历,求出该A的数量和,再求总和,这样显然超时。我发现,在最好的情况下,如果每对组合都是不同的数字(当然不可能),那么次数会是(1+2+3...+n-1)*2*n个,但是,有些两个Ai和Aj肯定会有重复数字,由于题目保证每个A都是内部无重复的,假设在所有的A中 1有k个, 那么,由于每个含有1的A往前求和的过程中,

1所造成的贡献就是1+2+...+n-1,这些全是等差数列,可以O(1)求出,而每次只会改一个数,我可以通过改的数字来求出这个数字的个数,比如,A0有1,A3中消除了1,那么cnt[1]增加2个

依次类推,最后,因为1<=a<=n+m,遍历范围每个数,然后减去贡献,就完成了 复杂度为O(sum(n+m))吧,反正不超

    int n,m;cin>>n>>m;
    map<int,int> sz,cnt;//sz记录数字出现的地方,cnt记录次数
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sz[a[i]]=1;
    }
    for(int i=2;i<m+2;i++){
        int x,y;cin>>x>>y;
        cnt[a[x]]+=i-sz[a[x]];
        sz[a[x]]=0;
        a[x]=y;
        sz[a[x]]=i;
    }
    for(int i=1;i<=n;i++) cnt[a[i]]+=m+2-sz[a[i]];
    //for(int i=1;i<=5;i++){
    //    cout<<i<<" : "<<cnt[i]<<"\n";
    //}
    ll ans=1LL*(1+m)*m*n;
    for(int i=1;i<=n+m;i++){
        if(cnt[i]==0||cnt[i]==1) continue;
        ans-=1LL*(cnt[i]-1)*cnt[i]/2;
    }
    cout<<ans<<"\n";
View Code

 

写出来3题还是很开心,尽管很弱,如果有大佬看到了,欢迎批评指正,新手上路罢了。后面补了再更新笔记

posted @ 2023-02-26 01:22  xishuiw  阅读(24)  评论(0编辑  收藏  举报