zoukankan      html  css  js  c++  java
  • 牛客编程巅峰赛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那么碎和追求比赛。

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

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

  • 相关阅读:
    饿了么P7级前端工程师进入大厂的面试经验
    前端程序员面试的坑,简历写上这一条信息会被虐死!
    这次来分享前端的九条bug吧
    移动端开发必会出现的问题和解决方案
    创建一个dynamics 365 CRM online plugin (八)
    创建一个dynamics 365 CRM online plugin (七)
    创建一个dynamics 365 CRM online plugin (六)
    创建一个dynamics 365 CRM online plugin (五)
    使用User Primary Email作为GUID的问题
    怎样Debug Dynamics 365 CRM Plugin
  • 原文地址:https://www.cnblogs.com/cmyg/p/14181614.html
Copyright © 2011-2022 走看看