首页 > 8.22美团笔试思路分享
头像
林不厌
编辑于 2020-08-22 20:18
+ 关注

8.22美团笔试思路分享

第一题判断字符串是否合法没啥好说的。
第二题是说每个物品的总价值是v[i]+2*w[i],问n个物品中价值最大的m个物品,对n个物品排序,排序的时候价值相同的物品取编号小的排在前面,价值不同的则价值大的排在前面,然后把前m个物品的编号放在set里面排序以后再输出。
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <utility>
using namespace std;

bool cmp(const pair<int, int>& a, const pair<int, int>& b)
{
	if (a.first == b.first)
		return a.second < b.second;
	return a.first > b.first;
}
int main()
{
	vector<pair<int, int>> vp;
	int n, m;
	cin >> n >> m;
	int v, w;
	for (int i = 1; i <= n; ++i){
		cin >> v >> w;
		vp.push_back(make_pair(v+2*w, i));
	}
	sort(vp.begin(), vp.end(), cmp);
	set<int> ans;
	for (int i = 0; i < m; ++i) ans.insert(vp[i].second);
	int flag = 0;
	for (int num : ans){
		if (flag) cout<< " ";
		cout << num;
		flag = 1;
	}
	cout << endl;
	return 0;
}
第三题是说在一个序列中按某个顺序取出数据,取完一个以后序列变成两个子序列,取完第二个变成三个子序列,每次取完数输出一下当前存在的子序列中和最大的值,但是样例给的太cao了,我误以为是每次取完数就只看左边和右边谁更大。
然而还是不会做,是线段树吗?我用树状数组+set暴力搞了一下,就是用set存放已经查询过的位置,然后暴力遍历区间,用树状数组求区间的和,更新ans,过了64%,应该不需要用long long,写的比较保险。
#include <iostream>
#include <cstring>
#include <cmath>
#include <set>
using namespace std;

int n;
long long fro[50010];
long long w[50010];

int lowbit(int x)
{
    return x&(-x);
}
void update(int pos, long long num)
{
    while (pos <= n)
    {
        fro[pos] += num;
        pos += lowbit(pos);
    }
}
long long get_sum(int pos)
{
    long long sum = 0;
    while (pos > 0)
    {
        sum += fro[pos];
        pos -= lowbit(pos);
    }
    return sum;
}

int main()
{
	cin >> n;
	memset(fro, 0, sizeof fro);
	for (int i = 1; i <= n; ++i){
		cin >> w[i];
		update(i, w[i]);
	}
	set<int> s;
	s.insert(0);
	s.insert(n);
	int index;
	for (int i = 1; i <= n; ++i){
		cin >> index;
		update(index, -w[index]);
		s.insert(index);
		set<int>::iterator p = s.begin();
		set<int>::iterator q = s.begin();
		++q;
		long long ans = 0;
		while (q != s.end()){
			long long x = get_sum(*q) - get_sum(*p);
			ans = max(ans, x);
			++p; 
			++q;
		}
		cout << ans << endl;
	}
	return 0;
}
第四题啥玩意。。。完全不会,题目很难读懂,读懂了也不会。

刚在讨论区找到了AC了第三题的大佬,把他的代码理解了一下。https://www.nowcoder.com/discuss/485678?type=0&order=0&pos=24&page=1&channel=666&source_id=discuss_center_0
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;

#define MAXN 50005
int a[MAXN];
int b[MAXN];
int sum[MAXN];
int ans[MAXN];

class UnionFind{//并查集模板
public:
    int n, count;
    vector<int> father;
    UnionFind(int num){
        n = count = num;
        father.resize(n);
        for(int i = 0 ; i < n ; i++)
            father[i] = i;
    }
    int find(int x){
        if(father[x] == x)
            return x;
        return find(father[x]);
    }
};
int main()
{
	int n;
	scanf("%d", &n);
    for(int i = 0 ; i < n ; i++)
        scanf("%d", &a[i]);
    for(int i = 0 ; i < n ; i++)
        scanf("%d", &b[i]);
    ans[n-1] = 0;
    int mmax = 0;
    UnionFind u(n);
    for(int i = n-1 ; i >= 0 ; i--){//倒着搞,把去除数字变成了插入数字,每插入一个位置,这个位置会变成所属堆的祖先,sum[id]是这个堆的和
        int id = b[i] - 1;
        sum[id]+= a[id];
        if(id > 0 && sum[id-1] > 0){//当插入的位置左边还没有被插入过数字时,说明当前数字不会跟左边的堆合并,否则去找左边位置的祖先,这个祖先是最近处理过的一个位置
            int x = id; 
            int y = u.find(id - 1);
            if(x != y){//其实x一定是不等于y的,因为x是第一次出现,y会等于x的左边最近计算过的一个位置,那个位置存放了x的左边的堆的和
                sum[x] += sum[y];
                u.father[y] = x;//左边的堆现在加到x上了,之后插入数字的时候如果x在数字旁边的堆,那就会find到x,sum[x]表示包含了x的堆的和,也就是说x现在变成了这个堆的祖先
            }
        }
        if(id < n-1 && sum[id+1] > 0){//同理,当插入的位置右边还没有被插入过数字时,说明当前数字不会跟右边的堆合并,否则可以把当前数字跟右边的堆合并成一个更大的堆

            int x = id; 
            int y = u.find(id + 1);
            if(x != y){
                sum[x] += sum[y];
                u.father[y] = x;//当前堆的祖先变成了x,且sum[x]表示这个堆的和
            }
        }
        mmax = max(mmax, sum[id]);//更新目前为止最大的堆,由于是插入,所以堆的最大值要么不变要么变成sum[x]了
        if(i > 0)
            ans[i-1] = mmax;//记录一下
    }
    for(int i = 0 ; i < n ; i++)//正向输出
        printf("%d\n", ans[i]);
    return 0;
}
真的太厉害了!这个反向操作实在高明!!!

全部评论

(17) 回帖
加载中...
话题 回帖

推荐话题

相关热帖

近期热帖

历年真题 真题热练榜 24小时
技术(软件)/信息技术类
查看全部

近期精华帖

热门推荐