• 牛客编程巅峰赛S2第10场


    感想放在最后

    10th场

    1. 没有准备好类Topcoder提交 -> 应该准备一个模板,比如 Solution sol; sol.xxx,更加节省时间

    A 尝试总结容易漏东西,这种题直接莽就完事了

    比赛中有考虑总结,然后就时间浪费了

    B 第一眼有点像冒泡排序(直接写就难受了……)

      还是先在纸上写写比较好

    C

    1.有经验的第一眼想到LowBit(树状数组)

    2.初学者打表找规律(事实上会快点)

    3.还有f(1)+...+f(2*i) 与 f(1)+...+f(i) 的规律挺好的~

    分治思想

    4.对应3,

    感觉 f(1)+...+f(2^i) 与 f(1)+...+f(2^(i-1)) 的规律更容易想

    5.强行打表。学到一招。sqrt(n)复杂度(如果允许);或者打k*1e8的数值。

    这应该是写得最快的……

    D

    这题挺好的

    这题这么多人过,但我觉得感觉不好想,也许是他们套路见识多了。下面2^20是个提示,这……

    把数字(二进制)拆位,单独与,但是求关于1的连通块。

    O(n*log(p))

    遇到数的->联想是否二进制拆位。其它比如数位DP

    赛后我想了树分治,

    于是有集合A的数分别与集合B的数求与,仔细一想还可以把某个集合里的数汇合起来,不过也要二进制拆位。

    看到有网友 多动手 用的是树形DP,

    每增加一个子节点,与之前的点进行交互,做到最后,就相当于两两进行交互,感觉挺巧妙的,代码也短。

    ===================================

     12th

    A

    C++占尽优势,如是说也

    我的itoa炸了,没有然后……

    其实while也挺快的(所以手速场就不应该尝试弄itoa这种自己也不熟,没有把握的东西

    to_string:to_string(s): ?->string

    sprintf(str_1,"?",?)

    甚至感觉高手是手打

    或者干脆用python写

    cb有问题:https://blog.csdn.net/u013271326/article/details/79613898(比赛呢?所以要学sprintf)

    C++

     1 class Solution {
     2 public:
     3     /**
     4      * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     5      * 判断x是不是好数
     6      * @param x int整型 待判断的数
     7      * @return bool布尔型
     8      */
     9     bool judge(int x) {
    10         //return to_string(x)[-1]==to_string(x)[0];
    11         string s=to_string(x);
    12         ///负值不行,坑~ Python可负
    13         //return s[-1]==s[0];
    14         return s[s.size()-1]==s[0];
    15     }
    16 };
     1 class Solution {
     2 public:
     3     /**
     4      * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     5      * 判断x是不是好数
     6      * @param x int整型 待判断的数
     7      * @return bool布尔型
     8      */
     9     bool judge(int x) {
    10         char s[100];
    11         sprintf(s,"%d",x);
    12         return s[strlen(s)-1]==s[0];
    13     }
    14 };

    Python

    class Solution:
        def judge(self , x ):
            # write code here
            x=str(x)
            return x[0]==x[-1]
    
    
    
    sol=Solution()
    print(sol.judge(1))
    print(sol.judge(123))

    TypeError: 'int' object is not subscriptable

    没有有下标

    B

    一眼直觉DP题

    一个序列,一个数的状态只与前一个有关系

    O(n^2)

    赛后有人说树状数组,O(nlogn);有的O(n^2logn)超了

    实际上,我看了大部分前排的代码,都是先固定中间,然后再选左右

    数目为N

    n=N-2

    1*n+2*(n-1)+...+n*1=(1+2+...+n)*n-(1*2+2*3+...+(n-1)*n)=1/6*n*(n+1)*(n+2),实在不明白为什么能过??!

    n=5000,value=20833332500

    当然固定了中间之后,也可以树状数组哦,从左往右加,从右往左加,也是O(nlogn)

    这就是典型的OIer思想啊,一开始竟然不往这里想

    另外,vector卡了很久……

    赛后修改

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <string>
     6 #include <vector>
     7 #include <algorithm>
     8 #include <iostream>
     9 using namespace std;
    10 #define ll long long
    11 const int maxn=5e3+10;
    12 
    13 const ll mod=1000000007;
    14 
    15 
    16 
    17 class Solution {
    18 public:
    19     /**
    20      * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
    21      *
    22      * @param arr int整型vector
    23      * @param a int整型
    24      * @param b int整型
    25      * @return int整型
    26      */
    27 
    28 
    29 
    30     int countTriplets(vector<int>& arr, int a, int b) {
    31         // write code here
    32         int f[maxn][2];
    33         int i,j,x,y,n=arr.size();
    34         ll sum=0;
    35         for (i=0;i<n;i++)
    36         {
    37             for (j=0;j<i;j++)
    38             {
    39                 if (abs(arr[i] - arr[j])<=a)
    40                     f[i][0]+=1;
    41                 if (abs(arr[i] - arr[j])<=b)
    42                     f[i][1]+=f[j][0];
    43             }
    44             sum+=f[i][1];
    45         }
    46         return sum%mod;
    47     }
    48 };
    49 
    50 //int main()
    51 //{
    52 //    Solution sol;
    53 //    vector<int> vec={7,1,8,9,0};
    54 ////    vector<int> vec={10,20,30,40,50};
    55 ////    vector<int> vec={10,10,10,10,10};
    56 //    cout<<sol.countTriplets(vec,3,3);
    57 //
    58 ////    cout<<sol.countTriplets([7,1,8,9,0],3,3);
    59 ////    //不行
    60 //
    61 //    return 0;
    62 //}
    63 
    64 //int main()
    65 //{
    66 //    int n=5000,i;
    67 //    ll sum=0;
    68 //    for (i=1;i<=n;i++)
    69 //        sum+=i*(n-i);
    70 //    cout<<sum;
    71 //    ///20833332500
    72 //}

    比赛时

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <string>
     6 #include <vector>
     7 #include <algorithm>
     8 #include <iostream>
     9 using namespace std;
    10 #define ll long long
    11 const int maxn=5e3+10;
    12 
    13 const ll mod=1000000007;
    14 
    15 
    16 
    17 class Solution {
    18 public:
    19     /**
    20      * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
    21      *
    22      * @param arr int整型vector
    23      * @param a int整型
    24      * @param b int整型
    25      * @return int整型
    26      */
    27 
    28 
    29 
    30     int countTriplets(vector<int>& arr, int a, int b) {
    31         // write code here
    32         int f[maxn][2];
    33         vector<int>::iterator it,ti;
    34         int i,j,x,y;
    35         ll sum=0;
    36         for (it=arr.begin(),i=0;it!=arr.end();it++,i++)
    37         {
    38             f[i][0]=1;
    39             x=*it;
    40             for (ti=arr.begin(),j=0;ti!=it;ti++,j++)
    41             {
    42                 y=*ti;
    43 //                if (abs((*it) , (*ti))<=a)
    44                 if (abs(x - y)<=a)
    45                     f[i][1]+=f[j][0];
    46 //                if (abs(*it , *ti)<=b)
    47                 if (abs(x - y)<=b)
    48                 {
    49                     f[i][2]+=f[j][1];
    50 
    51                 }
    52             }
    53             sum+=f[i][2];
    54         }
    55         return sum%mod;
    56     }
    57 };

    C

    问题思想:

    z 0 -z 规律

    拆分的思想,独立

    我的做法:

    数值扩大一倍,2z 0 -2z

    每个数 z 0 -z

    也有方法,是一开始全部-z(预处理),然后选就+z

     问题:

    1.cout了一发(所以一定要线下判一下……)

    2.vector……

    3.中途傻逼想网络流了。

    看到很多人也是想图论,什么负边,拆点……

    我的3发错误

    1. 没认真造样例,不太认真,蜜汁自信(事后发现错误还很多的)

    2. 无脑cout(之前有没有注释int main ,所以一定要线上(自判)、线下都判一下……)

    3. 为了避免数组出问题,把数组大小改为1e6,进行了初始化,过了

    但是神奇的是,

    1e5 无初始化 70%

    1e6 无初始化 过

    1e5 初始化 过

    数组放在外面 / 数组放在类里面而不是函数里面 1e5 无初始化

    贼神奇!

    建议好好了解一下评测机~~~

    怎么还是认为数组要初始化(一直怕,因为有前车之鉴)

    之前担心数组是否不能放在外面,经测试,不用担心(可以,尽量放外面,减去初始化什么的,避免各种神奇bug)

    /**
    networkflow
    ->dijkstra
    
    budui?
    
    同时奏响的额外优美程度是z,同时不奏响则为-z,其他情况为0
    ???
    a value z
    
    **/
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    #define ll long long
    const int maxn=1e6+10;
    
    class Solution {
    public:
        /**
         * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
         *
         * @param n int整型
         * @param m int整型
         * @param a int整型vector
         * @param b int整型vector<vector<>>
         * @return long长整型
         */
        long long wwork(int n, int m, vector<int>& a, vector<vector<int> >& b) {
            // write code here
    
    //        int fx[maxn];
    //        int fy[maxn][3],i,j;
    //        ll;
    
    //        vector<vector<int> >::iterator it2;
    //        vector<int>::iterator it1;
    //
    //        for (it1=a.begin(),j=0;it1!=a.end();it1++,j++)
    //            fx[j]=*it1;
    //        for (it2=b.begin(),i=0;it2!=b.end();it2++,i++)
    //            for (it1=it2.begin(),j=0;it1!=it2.end();it1++,j++)
    //                fy[i][j]=*it1;
    
    //        for (i=0;i<n;i++)
    ////            cout<<fx[i]<<endl;
    //            cout<<a[i]<<endl;
    //        for (i=0;i<m;i++)
    //            for (j=0;j<3;j++)
    //                cout<<b[i][j]<<endl;
    
    //                cout<<fy[i][j]<<endl;
    
    //        return ;
    
            int i,j;
            ll f[maxn],sum=0;
    
            ///both no -2z
            ///both yes 2z
            ///same 0
            ///
    
    //        for (i=0;i<n;i++)
    //            f[i]=0;
    
            ///if zouxiang
            for (i=0;i<m;i++)
                for (j=0;j<=1;j++)
                {
                    f[b[i][j]]+=b[i][2];
    //                cout<<b[i][j]<<" "<<b[i][2]<<endl;
                }
    
    //        cout<<endl;
    
            for (i=1;i<=n;i++)
            {
    //            cout<<f[i]+2*a[i-1]<<" "<<-f[i]<<endl;
                sum+=max( f[i]+2*a[i-1] , -f[i] );
            }
    
            return sum/2;
        }
    };
    
    //int main()
    //{
    //    Solution sol;
    //
    ////    vector<int> vec1={-10,-10};
    //////    vector<int> vec1={10,10};
    ////    vector<vector<int> > vec2;
    ////    vec2.push_back(vector<int>());
    ////    vec2[0].push_back(1);
    ////    vec2[0].push_back(2);
    ////    vec2[0].push_back(5);
    ////    cout<<sol.wwork(2,1,vec1,vec2);
    //
    ////    vector<int> vec1={3,5};
    //////    vector<int> vec1={10,10};
    ////    vector<vector<int> > vec2;
    ////    vec2.push_back(vector<int>());
    ////    vec2[0].push_back(1);
    ////    vec2[0].push_back(2);
    ////    vec2[0].push_back(7);
    ////    cout<<sol.wwork(2,1,vec1,vec2);
    //
    //
    //
    ////    vector<int> vec1={-10,-10,-10};
    //
    //    vector<int> vec1={10,10,10};
    //
    //    vector<vector<int> > vec2;
    //    vec2.push_back(vector<int>());
    //    vec2[0].push_back(1);
    //    vec2[0].push_back(2);
    //    vec2[0].push_back(10);
    //
    //    vec2.push_back(vector<int>());
    //    vec2[1].push_back(1);
    //    vec2[1].push_back(3);
    //    vec2[1].push_back(1000);
    //
    //    vec2.push_back(vector<int>());
    //    vec2[2].push_back(1);
    //    vec2[2].push_back(2);
    //    vec2[2].push_back(-100);
    //    cout<<sol.wwork(3,3,vec1,vec2);
    //    return 0;
    //}


    D

    题意理解

    • 首先是求最长的距离下的两点

    • 这两点在什么时候最短(旋转卡壳)

    • 这两个点在什么时候距离(二次函数,三分)

    题意弄懂后,就没问题了……

    ===================================

    赛前准备

    另一个桌面(打完后转回来!)

    文件创建快捷方式

    模板

      加上

      #include <string>

      #include <vector>

      但是太多也……(有万能代码)

    现在才发现有使用示例自测 示例1示例2示例3,可以手点……

    ===================================

    vector

    1. 可以直接vec[i],vec[i][j],大小vec.size(),感觉用vector<int>::iterator,vector<int>::reverse_iterator就……

    但是调试麻烦

    2.     cout<<sol.countTriplets([7,1,8,9,0],3,3);
        //不行

    vector<int> vec={7,1,8,9,0}; //ok 但是感觉很别扭,有更快的方法?

    为什么它那样输入([])就可以?

    3.

    https://www.cnblogs.com/xiaoxi666/p/6843211.html

    c++中常用的vector容器作为参数时,有三种传参方式,分别如下(为说明问题,用二维vector):

    • function1(std::vector<std::vector<int> > vec),传值
    • function2(std::vector<std::vector<int> >& vec),传引用
    • function3(std::vector<std::vector<int> >* vec),传指针

    注意,三种方式分别有对应的const形式,不在此讨论。

    三种方式对应的调用形式分别为:

    • function1(vec),传入值
    • function2(vec),传入引用
    • function3(&vec),传入地址

    三种方式的效果分别为:

    • 会发生拷贝构造
    • 不会发生拷贝构造
    • 不会发生拷贝构造

    4. vector转数组

    std::copy(vec.begin(), vec.arr(), arr);

     1 int main()
     2 {
     3     vector<int> vec={1,2,3};
     4     int arr[10];
     5 //    copy(vec.begin(),vec.end(),arr);
     6 //    arr=vec;
     7     for (int i=0;i<3;i++)
     8         cout<<arr[i]<<" ";
     9     return 0;
    10 }

    5. 功能

    push_back

    insert

    erase

    6.

    c++ vector 调试

    https://www.pianshen.com/article/7164927754/

    查看vector变量A当中元素的方法有2种:
    1.在“添加查看”中输入 A[0];
    2.在“添加查看”中输入 *(&A[0]);

    查看vector数组B[5]当中元素的方法也有2种:
    1.在“添加查看”中输入 B[3[0];
    2.在“添加查看”中输入 *(&B[3][0]);

    ==================

    调试:

    虽然可以直接注释掉 int main()

    别人的方法 https://ac.nowcoder.com/acm/contest/view-submission?submissionId=46228366

     1 #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
     2 void debug_out() { cerr << endl; }
     3   
     4 template <typename Head, typename... Tail>
     5 void debug_out(Head H, Tail... T) {
     6   cerr << " " << to_string(H);
     7   debug_out(T...);
     8 }
     9 
    10 #ifdef DEBUG
    11 XXX
    12 #endif

    ===================================

    科研散心过来打打,分别获得了10th场 rank 10th(3/3),12th场 21th(3/3)的成绩,赚了一个奖品,还行~

    主要讲述

      1. 用类Topcoder提交和vector的各种心酸历程,感觉很多基本的代码不会用,比如to_string那些(很久不用就忘了,加上本身自己就不擅长),然后就……

      2. 赛后思考的改代码,使写得更快

      3. 多种思路的交碰

    感觉

      1. 青铜&白银&黄金 感觉挺多S*B题(说实话第一个是奔着奖品去的),后来发现也有不少耳目一新的题目,学习了。听题解讲述发现不少题目与大众(Non-OI/ICPCer)思维不同

      2. 最后一场最后一题的处惊不乱,自我感觉还是不错的,有点ShengHua的感觉~

      3. 之后应该不会为了奖品打This Competition吧(吧吧)(感觉钻石&王者最后一题也不是太好过),不为五斗米折腰(逃),要勇闯CF Div1啊啊啊,不要畏缩在CF Div 2(希望自己水平能高点吧)。

      4. 在研究生中,

        更加体会到实际问题 & 理论研究部。

        有时也不追求时间,能做出来就好(工程)。

        也有非最完美算法,比如近似算法,启发式搜索。

        对于算法的研究会更加体系化,感觉没有ICPC那么碎和追求比赛。

        自己对于算法的学习,会更加契合于自己研究课题,并追求于学习更有挑战的知识和思想,而不是像之前不断巩固算法和提高手速,然后有时做题有些重复和难度低,感觉这样学习算法不太好,会学得比较慢和没有激情,挥霍青春。现在心态比较放松,感觉大学时有时心态复杂,有时打比赛经常没有发挥应有的水平。

        逐渐感觉到数学的重要性,所以好好学习数学吧。

  • 相关阅读:
    ORACLE触发器简单列子
    接口测试中需要携带token的接口返回结果偶尔报无权限
    接口自动化测试用例偶尔报无权限的解决办法
    python中的faker库生成数据,并写入txt文本中
    anaconda在sys.path删除~/.local/lib
    题解12/12 模拟赛
    题解BalticOI 2020
    题解12/09 模拟赛
    亿些原古博客汇总
    bijective proof problems 选做
  • 原文地址:https://www.cnblogs.com/cmyg/p/14181614.html
Copyright © 2020-2023  润新知