【自动车class="superseo">class="superseo">算法岗】差了5秒钟,终究还是没能AK呀。第三题一开始只对了18%的数据,在还有20分钟的时候,发现题目看错了,码到 cout<
笔试题分为两大部分:4道算法题+3道人工智能相关知识的多选题。限时两个小时,每个子部分提交后可以再返回修改,这点还是很人性化的,不像有的笔试,子部分提交后就无法返回修改了,就不是那么的友好了。
题目大概都是力扣 [mid~hard] 的难度,下面切入正题吧!由于晚上还有一场笔试,具体的思路证明之类的以后再补了哈,先贴一下Code
第一题_四川麻将 题意
玩法是摸完牌之后选择3张花色一样的牌按某种顺序换给其他人。为了尽可能破坏对手的游戏体验,每次都会选择不连续的3张牌换出去。比如手上有 {1 4 5 6 8} 这5张条子,则可能会选择 {1 5 8} 这三张条子换出去。
把这个问题进行了简化,现在给你一个可重集合,并希望你从中选出一个尽可能大的子集使得其中没有两个数是 “连续” 的。
输入
第一行一个整数n(1<=n<=100000),代表可重集大小
第二行n个空格隔开的整数(范围在1到200000之间),代表可重集
输出
输出满足条件的最大子集的大小
样例数据AC_Code输入
6
1 2 3 5 6 7
输出
4
#include
using namespace std;
const int N = 1e5+10, M = 2e5+10;
int n, a[N], dp[M];
int main() {
cin>>n;
for(int i=1; i<=n; i++) cin>>a[i];
for(int i=1; i<=n; i++) dp[a[i]] = 1 ;
for(int i=1; i
第二题_翻转最大子段和 题意
最大子段和是力扣上比较经典问题。这里对它进行了改编,允许在求解该问题之前翻转这个数组的连续一段,如翻转 (1,2,3.45.6) 的第3个到第5个元素组成的子数组得到的是 (1,2,5,4,3,6),求翻转后该数组的最大子段和最大能达到多少。
输入输出描述输入
第一行—个正整数n,(1<=n<=100000),代表数组长度
第二行n个空格隔开的整数 (-1000<=ai< =1000),代表数组元素大小
输出
求翻转后所得数组的最大子段和
样例数据AC_Code输入
6
-1 3 -5 2 -1 3
输出
7
#include
using namespace std;
const int N = 1e5+10, inf = 1e9+10;
int n, a[N], p[N], s[N];
void solve() {
p[0] = -inf;
int sum=0;
for(int i=1; i<=n; i++) {
sum = max(0, sum) + a[i];
p[i] = max(p[i-1], sum);
}
s[n+1]=-inf; sum=0;
for(int i=n; i>=1; i--) {
sum = max(0, sum) + a[i];
s[i] = max(s[i+1], sum);
}
}
int main() {
cin>>n;
for(int i=1; i<=n; i++) cin>>a[i];
solve();
int ma = *max_element(p+1, p+n+1);
for(int i=1; i
第三题_切豆腐 题意
为了切出更均匀的豆腐,想知道每一次下刀之后切出来的豆腐块中体积最大的那块有多大。
输入输出描述第一行两个整数n,m (1<=n,m<=1000),代表最开始长宽高均为n厘米,总共切了m刀。
第二行m个小写字母,每个字母都是 x,y,z 中的一个。第i个代表刀垂直于哪个坐标轴。
第三行m个大于0且小于n的正整数。第i个代表第i刀所在平面到豆腐的右上角 (或者任选一个角并固定,无论选哪个角答案均相同) 的距离。
保证切的时候豆腐不会产生形变且不会产生位移。每次下刀都会把整块豆腐切开,不存在切到一半收刀,切出来的每块小豆腐都是边长为正整数的长方体。
AC_Code输入
2 3
x y z
1 1 1
输出
4
2
1
#include
using namespace std;
const int N = 1e5+10, M = 2e5+10;
int n, m;
int main()
{
cin >> n >> m;
vector op(m+1);
for(int i=1; i<=m; i++) cin>>op[i];
vector v(m+1);
for(int i=1; i<=m; i++) cin>>v[i];
multiset x,y,z;
x.insert(0), x.insert(n);
y.insert(0), y.insert(n);
z.insert(0), z.insert(n);
for(int i=1; i<=m; i++)
{
if(op[i][0]=='x') x.insert(v[i]);
else if(op[i][0]=='y') y.insert(v[i]);
else if(op[i][0]=='z') z.insert(v[i]);
}
int mx=0, my=0, mz=0, pre=0;
for(auto it:x) mx = max(mx,it-pre), pre=it;
pre=0;
for(auto it:y) my = max(mx,it-pre), pre=it;
pre=0;
for(auto it:z) mz = max(mx,it-pre), pre=it;
vector ans(m+1);
for(int i=m; i>=1; i--)
{
ans[i] = mx*my*mz;
if(op[i][0]=='x')
{
auto it = x.find(v[i]);
int suf = *(++it);
it--;
int pre = *(--it);
mx = max(mx, suf-pre);
x.erase(v[i]);
}
if(op[i][0]=='y')
{
auto it = y.find(v[i]);
int suf = *(++it);
it--;
int pre = *(--it);
my = max(my, suf-pre);
y.erase(v[i]);
}
if(op[i][0]=='z')
{
auto it = z.find(v[i]);
int suf = *(++it);
it--;
int pre = *(--it);
mz = max(mz, suf-pre);
z.erase(v[i]);
}
}
for(int i=1; i<=m; i++)
cout << ans[i] << endl;
return 0;
}
第四题_区间 *** 作求和 题意
给出一个长度为n的数组,进行m次数组上的区间 *** 作, *** 作包含将区间内所有数加上一个值和查询一个区间内所有数的和。如果允许重新排列初始数组中的元素并依次进行 *** 作,则 *** 作中所有查询区间和的答案之和能够达到多大?
输入输出描述输入
第一行有两个数 n,m(1<=n=<5000,1<=m<=500),代表数组长度和操作次数。第二行有n个数,代表初始数组中的元素,接下来m行每行 1 l r 或 2 l r k,分别代表查询下标属于 [l,r] 的元素之和这一揭作和将下标属于 [l,r] 的元素全部加上定值k。l r k 满足1<=l<=r<=n,1<=k<=5000
输出
输出若允许重新排列初始数组,进行m次 *** 作后产生的所有输出之和最大值
样例数据AC_Code输入
5 5
3 4 2 1 5
1 1 3
2 3 4 2
1 2 4
2 2 3 2
1 3 5
输出
42
#include
using namespace std;
const int N = 1e5+10, M = 2e5+10;
int n, m;
int main() {
cin>>n>>m;
vector a(n+1);
for(int i=1; i<=n; i++) cin>>a[i];
ll ans_sum=0;
vector cnt(n+1),add(n+1);
for(int i=1; i<=m; i++) {
int op; cin>>op;
if(op==1) {
int l,r;
cin>>l>>r;
for(int i=l; i<=r; i++) cnt[i]++, ans_sum += add[i];
}
else{
int l,r,k;
cin>>l>>r>>k;
for(int i=l; i<=r; i++) add[i] += k;
}
}
sort(a.begin()+1,a.end());
sort(cnt.begin()+1,cnt.end());
for(int i=1; i<=n; i++)
ans_sum += 1LL * cnt[i] * a[i];
cout << ans_sum << endl;
return 0;
}
OVER~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)