0919滴滴笔试编程题代码+思路
首先是第二题,求连续的最小长度为m的数组和的最小值。
#include<algorithm> #include<cstdio> using namespace std; int n,m; int num[111111],sum[111111]; int ans; int mn; int main() { scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&num[i]); sum[i]=sum[i-1]+num[i]; if(i==m) { ans=sum[i]; } else if(i>m) { mn=max(mn,sum[i-m]); ans=min(ans,sum[i]-mn); } } printf("%d\n",ans); }
其实挺简单的,思路就是扫一遍,算前缀和,对于一个区间[l,r],当我的r固定时,首先要满足令l+m-1<=r,即1<=l<=r+1-m
现在我们相当于对于每一个r确定了l的范围,而[l,r]的和等于sum[r]-sum[l-1]为了是区间和尽可能的小,那么当sum[r]固定时,就是对于所有的l的取值找出sum[l-1]的最大值,
接下来对于每一个r的取值,来更新全局的答案就行了,相当于就是一个循环就能做完了。
第一题,笔试的时候想错了一个地方,只过了55%
#include<iostream> #include<queue> #include<cstring> #include<algorithm> #include<cstdio> #include<map> using namespace std; int n,m; int a,b; int cnt; int pre[555]; int num[555]; map<int,int>map1; map<int,int>map2; int tot=1; int Find(int a) { if(pre[a]!=a) pre[a]=Find(pre[a]); return pre[a]; } void Union(int x,int y) { int fx=Find(x); int fy=Find(y); if(fx==fy) { num[tot++]=fx; } else pre[fy]=fx; } int main() { scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) pre[i]=i; for(int i=0;i<m;i++) { scanf("%d %d",&a,&b); Union(a,b); } for(int i=1;i<=n;i++) { int x=Find(i); map1[x]++; } for(int i=1;i<tot;i++) { if(map1[num[i]]%2==1) { n--; } } if(n%2==0) printf("%d\n",n); else printf("%d\n",n-1); }
首先根据题意,一堆垃圾最多只有两个约束条件,相当于一个点最多连两条边,那么这个图就只存在孤立点、单链和简单的环,这里我们需要注意,有奇数个点的环是非法的
首先是解除非法的情况,就是说对于一个有奇数点的环,我们要删去一个点(n--)
然后对于所有的合法情况,我们会发现,所有的环或者是链,其染色后的两种颜色的节点个数差最多是1个
也就是说在分配两个车的垃圾的时候我们至多会出现一个车的垃圾比另外一个车多1个的现象
如果所有的垃圾都分配完毕,还存在这种情况,那么只需要从多的那个垃圾车上边扔下来一袋垃圾就可以了,这样就不会破坏约束了
所以说实际上代码就是先判断是否存在奇数点的环,存在一个n-1,最后判断n的奇偶性就行了。