网易机试
一、
1、
#include<iostream> #include<algorithm> #include<vector> using namespace std; int Inte[100000]; int SlpOrCle[100000]; int SlpOrCle1[100000]; int SumInte1(int *a,int *b,int n) //求兴趣点; { int suminte1=0; for(int i=0;i<n;i++) { if(b[i]==1) suminte1+=a[i]; } return suminte1; } int main() { int n,k; while(cin>>n>>k) //输入第一行 { int Maxinte=0; for(int i=0;i<n;i++) cin>>Inte[i]; //输入第二行 for(int i=0;i<n;i++) cin>>SlpOrCle[i]; //输入第三行 for(int i=0;i<n;i++) SlpOrCle1[i]=SlpOrCle[i]; //复制数据。 vector<int> Zeros; //存放0的位置 for(int i=0;i<n;i++) { if(SlpOrCle[i]==0) Zeros.push_back(i); } for(int i=0;i<Zeros.size();i++) { for(int j=Zeros[i];j<(Zeros[i]+k) and j<n;j++) { SlpOrCle1[j]=1; //叫醒后,置1 } int a; a=SumInte1(Inte,SlpOrCle1,n); //调用函数,n为课堂分钟 if(a>Maxinte) { Maxinte=a; //找最大的 } for(int i=0;i<n;i++) SlpOrCle1[i]=SlpOrCle[i]; //归为原始数据 } cout<<Maxinte; } return 0; } //6 3 1 3 5 2 5 4 1 1 0 1 0 0
通过率50% ,运行超时。
思路其实是,循环搜索所有的0位置,置为1,每次需要把所有的值重新计算一遍,当数据量大时,就会超时。
2、
每次叫醒后,都会新增一部分兴趣值,所以只需要找出最大的新增的兴趣值就可。然后加上本来就醒着的兴趣值。
#include<iostream> #include<algorithm> #include<vector> using namespace std; int Inte[100000]; int SlpOrCle[100000]; int SlpOrCle1[100000]; int main() { int n,k; while(cin>>n>>k) //输入第一行 { int Maxinte=0; for(int i=0;i<n;i++) cin>>Inte[i]; //输入第二行 ,兴趣值 for(int i=0;i<n;i++) cin>>SlpOrCle[i]; //输入第三行,清醒or瞌睡 vector<int> Zeros; //存放0的位置 for(int i=0;i<n;i++) { if(SlpOrCle[i]==0) Zeros.push_back(i); } int OriInte=0; for(int i=0;i<n;i++) { if(SlpOrCle[i]==1) { OriInte+=Inte[i]; //最初的兴趣值 } } int MaxAddInte=0; for(int i=0;i<Zeros.size();i++) { int InteTem=0; for(int j=Zeros[i];j<(Zeros[i]+k) and j<n;j++) //每个叫醒点,后面的k个值,新增的兴趣值,找出最大 { if(SlpOrCle[j]==0) { InteTem+=Inte[j]; //增加的兴趣值 } } if(MaxAddInte<InteTem) MaxAddInte=InteTem; //找出最大的新增的兴趣值 } Maxinte=OriInte+MaxAddInte; cout<<Maxinte; } return 0; } //6 3 1 3 5 2 5 4 1 1 0 1 0 0
通过 90%。
上面代码优化了不用每次都计算所有的兴趣值,转化为 固定的兴趣值+新增的最大兴趣值
找最大兴趣值是依次搜索0的位置,其后的k个值中,睡着的兴趣值相加。当K很大时,依旧会造成重复计算。
3、k个数据依次右移的方法来找最大的新增兴趣值。
#include<iostream> #include<vector> using namespace std; int Inte[100000]; int SlpOrCle[100000]; int SlpOrCle1[100000]; int MaxAddInte(int *a,int *b,int n,int k) { int maxInte=0; int temInte=0; for(int i=0;i<k;i++) //得到第一个k组数中0对应的兴趣和 { if(b[i]==0) { temInte+=a[i]; } } maxInte=temInte; for(int i=k;i<n;i++) //k组右移 { if(b[i]==0) //右移一位,判断加的位置为0,兴趣值加 { temInte+=a[i]; } if(b[i-k]==0) //右移一位,判断最左边少的位置为0,则减 { temInte-=a[i-k]; } if(temInte>maxInte) //右移一位后,判断最大新增值 maxInte=temInte; } return maxInte; } int main() { int n,k; while(cin>>n>>k) //输入第一行 { int Maxinte=0; for(int i=0;i<n;i++) cin>>Inte[i]; //输入第二行 ,兴趣值 for(int i=0;i<n;i++) cin>>SlpOrCle[i]; //输入第三行,清醒or瞌睡 vector<int> Zeros; //存放0的位置 int OriInte=0; for(int i=0;i<n;i++) { if(SlpOrCle[i]==0) Zeros.push_back(i); else OriInte+=Inte[i]; //最初的兴趣值 } int AddInte; AddInte=MaxAddInte(Inte,SlpOrCle,n,k); Maxinte=OriInte+AddInte; cout<<Maxinte; } return 0; } //6 3 1 3 5 2 5 4 1 1 0 1 0 0
测例全部通过。
二、
1、先求和再查找的过程
#include <iostream> using namespace std; int ap[100000]; int qu[100000]; int Quiry(int *a,int b,int n) //查询在第几堆 { if(b<a[0]) return 1; int i=0; while(a[i]<b and a[i+1]<b) //从小到大查询 { i++; } return i+2; } int main() { int n,m; while(cin>>n) { int tem=0; for(int i=0;i<n;i++) { int num; cin>>num; tem=tem+num; ap[i]=tem; //苹果个数累和 } cin>>m; for(int i=0;i<m;i++) { cin>>qu[i]; //查询的数量 } for(int i=0;i<m;i++) { cout<<Quiry(ap,qu[i],n)<<" "; } } return 0; } //5 2 7 3 4 9 3 1 25 11
从小到大的查询,时间复杂度太大。
2、
#include <iostream> #include<math.h> using namespace std; int ap[100000]; int qu[100000]; int Quiry(int *a,int b,int n) //二分法查询 { if(b<a[0]) return 1; //特殊情况 int imin=0,imax=n; while((imax-imin)>1) { if( b>a[(int)ceil((imin+imax)/2)] ) imin=(int)ceil((imin+imax)/2); else imax=(int)ceil((imin+imax)/2); } return imax+1; } int main() { int n,m; while(cin>>n) { int tem=0; for(int i=0;i<n;i++) { int num; cin>>num; tem=tem+num; ap[i]=tem; //苹果个数累和 } cin>>m; for(int i=0;i<m;i++) { cin>>qu[i]; //查询的数量 } for(int i=0;i<m;i++) { cout<<Quiry(ap,qu[i],n)<<endl; } } return 0; } //5 2 7 3 4 9 3 1 25 11
通过所有用例。
3、利用c++ stl
一个数组number序列为:4,10,11,30,69,70,96,100.设要插入数字3,9,111.pos为要插入的位置的下标
则
pos = lower_bound( number, number + 8, 3) - number,pos = 0.即number数组的下标为0的位置。
pos = lower_bound( number, number + 8, 9) - number, pos = 1,即number数组的下标为1的位置(即10所在的位置)。
pos = lower_bound( number, number + 8, 111) - number, pos = 8,即number数组的下标为8的位置(但下标上限为7,所以返回最后一个元素的下一个元素)。
所以,要记住:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!~
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; int n,m,t; ll a[100005]; ll q; int main() { cin>>n; a[0]=0; for(int i=1;i<=n;i++){ cin>>t; a[i]=a[i-1]+t; //苹果累和 } cin>>m; for(int i=0;i<m;i++){ cin>>q; int loc=lower_bound(a+1,a+n+1,q)-a; //利用stl 来查找位置 cout<<loc<<endl; } return 0; }
4、
#include <iostream> #include<math.h> using namespace std; int ap[100000]; int qu[100000]; int main() { int n,m; while(cin>>n) { int tem=0; for(int i=1;i<=n;i++) { int num; cin>>num; tem=tem+num; for(int j=tem-num+1;j<=tem;j++) { ap[j]=i; cout<<ap[j]<<" "; } cout<<endl; } for(int j=1;j<=25;j++) { cout<<ap[j]<<" "; } cin>>m; for(int i=0;i<m;i++) { cin>>qu[i]; //查询的数量 } for(int i=0;i<m;i++) { cout<<ap[qu[i]]<<endl; } } return 0; } //5 2 7 3 4 9 3 1 25 11
思路是生成一个向量,将所有的苹果的堆数存入该向量。第i个苹果的堆数为ap[i]。
但通过率30%。
可以看到测试用例很大,所以将所有苹果都生成向量,计算量过大,不会完全通过。
三、
#include <iostream> #include <vector> using namespace std; int main() { int a,b,c; while(cin>>a>>b>>c) { int Max; Max=a+b+c; if(Max<(a*b*c)) Max=a*b*c; if(Max<((a+b)*c)) Max=(a+b)*c; if(Max<((a+c)*b)) Max=(a+c)*b; if(Max<((c+b)*a)) Max=(c+b)*a; cout<<Max; } return 0; }
所有公式计算下,找最大的就可以了。
题很简单,没难度。
四、
相当于统计1、2、3的个数,找出最小的个数值,就为应得的分数。
#include<iostream> using namespace std; int main() { int m=0,n=0,mid; cin>>n>>m; int a[100000]={0,0}; for(int i=0;i<m;i++) { cin>>mid; a[mid]++; } mid =m+1; for(int i=1;i<=n;i++) { if(mid>a[i]) mid =a[i]; // cout<<a[i]<<' '; } cout<<mid<<endl; return 0; }