题目链接:https://www.nowcoder.com/test/9763997/summary
1.牛牛找工作:
为了找到自己满意的工作,牛牛收集了每种工作的难度和报酬。牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作。在牛牛选定了自己的工作后,牛牛的小伙伴们来找牛牛帮忙选工作,牛牛依然使用自己的标准来帮助小伙伴们。牛牛的小伙伴太多了,于是他只好把这个任务交给了你。
解题思路分析:
每个工作都有自己的难度和工资,我们需要求的是每一个人能承受的难度中工资最高的,首先分析能否能用一次排序就达到效果,如果把难度作为关键字排序的话,那么在排好序中的序列中,也不能直接得到答案,所以我们需要将排好序的序列中维护一个前缀数组,记录从前面到当前位置的最高工资,因为我们的序列是按难度排序的,所以排在前面的难度一定不会比后面的高,所以这个前缀数组是可维护的,接下来我们再通过二分查找找到每个人相应的难度位置,再通过查询前缀数组得到答案。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100000+5;
struct Node {
int d, p;
}node[maxn];
int Max[maxn];
int cmp(Node a, Node b) {
return a.d < b.d;
}
int main() {
int n, m;
cin >> n >> m;
for(int i=0; i<n; i++) {
cin >> node[i].d >> node[i].p;
}
sort(node, node+n, cmp);
for(int i=0; i<n; i++) {
if(i != 0) {
Max[i] = max(Max[i-1], node[i].p);
}
else {
Max[i] = node[i].p;
}
}
for(int i=0; i<m; i++) {
int tmp;
cin >> tmp;
int L = 0, R = n-1, Mid;
while(L < R) {
Mid = L + ((R - L) >> 1);
if(node[Mid].d <= tmp) {
L = Mid + 1;
}
else {
R = Mid;
}
}
if(node[L].d == tmp) {
cout << Max[L] << endl;
}
else {
cout << Max[L-1] << endl;
}
}
}
2.被3整除:
小Q得到一个神奇的数列: 1, 12, 123,...12345678910,1234567891011...。
并且小Q对于能否被3整除这个性质很感兴趣。
小Q现在希望你能帮他计算一下从数列的第l个到第r个(包含端点)有多少个数可以被3整除。
解题思路分析;
打个表,其实规律一眼就能看出来,这种题真的不用去纠结为什么,等做完题了再想也来得及,规律:
1 12 123 1234 12345 123456 1234567……
0 1 1 0 1 1 0……
显然是011011011……的循环
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int l, r;
while(cin >> l >> r) {
l--;
int nl = (l/3)*2 + (l%3) - 1;
int nr = (r/3)*2 + (r%3) - 1;
cout << nr - nl << endl;
}
return 0;
}
3.安置路灯
小Q正在给一条长度为n的道路设计路灯安置方案。
为了让问题更简单,小Q把道路视为n个方格,需要照亮的地方用'.'表示, 不需要照亮的障碍物格子用'X'表示。
小Q现在要在道路上设置一些路灯, 对于安置在pos位置的路灯, 这盏路灯可以照亮pos - 1, pos, pos + 1这三个位置。
小Q希望能安置尽量少的路灯照亮所有'.'区域, 希望你能帮他计算一下最少需要多少盏路灯。
解题思路分析:
其实只要做到没有两个灯之间重合,尽可能得不浪费灯在不需要照亮的地方,一定是能得到最终答案的。小编的做法就是,从左往右遍历,遇到一个需要照亮的地方,就在它的下一个位置放一盏灯,然后将这三个位置改为'X'即可。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1000+5;
char str[maxn];
int main() {
int T;
cin >> T;
while(T--) {
int n;
cin >> n >> str;
int num = 0;
for(int i=0; i<n; i++) {
if(str[i] == '.') {
num++;
str[i] = str[i+1] = str[i+2] = 'X';
}
}
cout << num << endl;
}
}
4.迷路的牛牛
牛牛去犇犇老师家补课,出门的时候面向北方,但是现在他迷路了。虽然他手里有一张地图,但是他需要知道自己面向哪个方向,请你帮帮他。
解题思路分析:
这题应该是最简单的题了吧,首先四个L或R就相当于转了一圈,一个L一个R相当于没动,L和R的顺序改变不会影响结果,所以只需要稍微处理一下就可得到答案。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1000+5;
char str[maxn];
char dir[4] = {'N', 'E', 'S', 'W'};
int main() {
int n;
cin >> n >> str;
int nL = 0, nR = 0;
for(int i=0; i<n; i++) {
if(str[i] == 'L') {
nL++;
}
else {
nR++;
}
}
nL %= 4;
nR %= 4;
// cout << nL << nR << endl;
if(nR > nL) {
cout << dir[(nR - nL)%4] << endl;
}
else if(nR < nL){
cout << dir[4 - (nL - nR)%4] << endl;
}
else {
cout << 'N' << endl;
}
return 0;
}
5.数对:
牛牛以前在老师那里得到了一个正整数数对(x, y), 牛牛忘记他们具体是多少了。
但是牛牛记得老师告诉过他x和y均不大于n, 并且x除以y的余数大于等于k。
牛牛希望你能帮他计算一共有多少个可能的数对。
解题思路分析:
首先,答案中的数对里y一定是大于k的,对于每一个y,我们都能通过取模求得有多少个合法的x,所以我们只需要枚举所有的y即可得到答案。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
int main() {
int n, k;
cin >> n >> k;
if(k == 0) {
cout << (LL)n*n << endl;
return 0;
}
LL num = 0;
for(int i=k; i<=n; i++) {
int x = n / i;
num += x * (i - k);
if((n % i) >= k) {
num += (n % i) - k + 1;
}
}
cout << num << endl;
return 0;
}
6.矩形重叠:
平面内有n个矩形, 第i个矩形的左下角坐标为(x1[i], y1[i]), 右上角坐标为(x2[i], y2[i])。
如果两个或者多个矩形有公共区域则认为它们是相互重叠的(不考虑边界和角落)。
请你计算出平面内重叠矩形数量最多的地方,有多少个矩形相互重叠。
解题思路分析:
因为这个题小编当时在做的时候是没有做出这道题的,所以小编也不马后炮拿别人的思路来讲了,这题我看到很多人有很多不同的做法,这道题数据只有50,甚至在O(n^3)范围内都是能做出来的。
7.牛牛的闹钟:
牛牛总是睡过头,所以他定了很多闹钟,只有在闹钟响的时候他才会醒过来并且决定起不起床。从他起床算起他需要X分钟到达教室,上课时间为当天的A时B分,请问他最晚可以什么时间起床
解题思路分析:
首先这题需要做两个处理,第一,把带小时和分钟的两个变量存储为小时*60 + 分钟的一个变量,这样的转换是可以逆转的,。第二,把每一个时间都加上24小时再存储一遍,并把目标时间也加上24小时,这样处理可以灵活得解决过了一天小时从23又变为0这种情况,解决这个问题后只需要排序再进行二分查找即可得到答案。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100+5;
int t[maxn];
int main() {
int n;
cin >> n;
for(int i=0; i<n; i++) {
int a, b;
cin >> a >> b;
t[i] = a * 60 + b;
t[n+i] = (a+24) * 60 + b;
}
sort(t, t+2*n);
int x, A, B, T;
cin >> x >> A >> B;
T = (A+24) * 60 + B - x;
int L = 0, R = 2*n-1, Mid;
while(L < R) {
Mid = L + ((R - L) >> 1);
if(t[Mid] < T) {
L = Mid + 1;
}
else {
R = Mid;
}
}
if(t[L] > T) {
L--;
}
int H = t[L] / 60;
int M = t[L] % 60;
H %= 24;
cout << H << " " << M << endl;
}
8.牛牛的背包问题:
牛牛准备参加学校组织的春游, 出发前牛牛准备往背包里装入一些零食, 牛牛的背包容量为w。
牛牛家里一共有n袋零食, 第i袋零食体积为v[i]。
牛牛想知道在总体积不超过背包容量的情况下,他一共有多少种零食放法(总体积为0也算一种放法)。
解题思路分析:
这其实不是一个背包问题啊,题目是问我们有多少种方法,因为题目的数据只有35,那么仔细一分析,最多2^35的情况,那么我们可以直接DFS搜索答案,特殊处理w大于所有物品总和的情况即可。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 35;
LL v[40];
int n;
LL ans=0,w;
void dfs(int t, LL sum) {
ans++;
if(t == n-1){
return ;
}
for(int i=t+1; i<n; i++) {
if(sum+v[i] <= w) {
dfs(i,sum+v[i]);
}
}
}
int main() {
cin >> n >> w;
LL sum = 0;
for(int i=0; i<n; i++) {
cin >> v[i];
sum += v[i];
}
if(sum <= w) {
ans = 1 << n;
}
else {
dfs(-1, 0);
}
cout << ans << endl;
return 0;
}