牛客编程巅峰赛S2第10场 - 青铜&白银&黄金 & 牛客编程巅峰赛S2第12场 - 青铜&白银&黄金 & 看 钻石&王者题目
感想放在最后
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>
但是太多也……(有万能代码)
===================================
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那么碎和追求比赛。
自己对于算法的学习,会更加契合于自己研究课题,并追求于学习更有挑战的知识和思想,而不是像之前不断巩固算法和提高手速,然后有时做题有些重复和难度低,感觉这样学习算法不太好,会学得比较慢和没有激情,挥霍青春。现在心态比较放松,感觉大学时有时心态复杂,有时打比赛经常没有发挥应有的水平。
逐渐感觉到数学的重要性,所以好好学习数学吧。