搜狗2016研发工程师编程题

来源:互联网 发布:软件结项文档 编辑:程序博客网 时间:2024/05/19 21:41

题目链接:点这里.

这套题目还是很有质量的,都是暴力过不了的题,但是觉得牛客网数据还是有点水,很多人都暴力过了……,第一题要二分,而且选对数据结构对代码的复杂度有很大的减低;第二题简单的动态规划,处理好非负数就好了.

第一题:火眼金睛

题目:

现在我们需要查出一些作弊的问答社区中的ID,作弊有两种:1.A回答了B的问题,同时B回答了A的问题。那么A和B都是作弊。2.作弊ID用户A和作弊ID用户B同时回答了C的问题,那么C也是作弊。已知每个用户的ID是一串数字,一个问题可能有多个人回答。

解析:

首先要考虑ID可能是离散的,所以要双向map,不过后台数据貌似是连续的;

其次先求出第一种方式作弊的ID,这里要用到二分,选用的是STL中的set,自动二分查找而且不用考虑重复的问题,然后用选出的ID不断选出第二种方式作弊的ID;

最后再把连续的ID映射回原ID,这里也用set,自动排序.

代码:

#include <bits/stdc++.h>using namespace std;int main(){    int n;    while (~scanf("%d", &n)) {        map<int, int> mp, toSrc;        int ids = 0;        vector<set<int> > arr(n + 1);        for (int i = 0; i < n; i++) {            int id_top, numOfAnswer;            scanf("%d%d", &id_top, &numOfAnswer);            if (mp.find(id_top) == mp.cend())                mp[id_top] = ids++, toSrc[mp[id_top]] = id_top;            int question = mp[id_top];            for (int j = 0; j < numOfAnswer; j++) {                int id;                scanf("%d", &id);                if (mp.find(id) == mp.cend())                    mp[id] = ids++, toSrc[mp[id]] = id;                if (mp[id] == question)                    continue;                arr[question].insert(mp[id]);            }        }        set<int> ans;        for (int i = 0; i < n; i++) {            for (auto it = arr[i].begin(); it != arr[i].end(); ++it) {                if (arr[*it].find(i) != arr[*it].cend()) {                    ans.insert(i);                    ans.insert(*it);                }            }        }        while (true) {            bool isOk = true;            for (int i = 0; i < n; i++) {                if (ans.find(i) != ans.cend())                    continue;                for (auto it1 = arr[i].begin(); it1 != arr[i].end(); ++it1) {                    auto it2 = it1;                    for (++it2; it2 != arr[i].end(); ++it2) {                        if (ans.find(*it1) != ans.cend() && ans.find(*it2) != ans.cend()) {                            isOk = false;                            ans.insert(i);                            goto F;                        }                    }                }                F:;            }            if (isOk)                break;        }        set<int> theAns;        for (auto it = ans.begin(); it != ans.end(); ++it)            theAns.insert(toSrc[*it]);        printf("%d\n", theAns.size());        bool isFirst = true;        for (auto it = theAns.begin(); it != theAns.end(); ++it) {            if (!isFirst)                putchar(' ');            isFirst = false;            printf("%d", *it);        }        if (!isFirst)            puts("");    }    return 0;}

第二题:矩阵元素相乘

题目:

A[n,m]是一个nm列的矩阵,a[i,j]表示A的第ij列的元素,定义x[i,j]A的第i行和第j列除了a[i,j]之外所有元素(共n+m2个)的乘积,即x[i,j]=a[i,1]a[i,2]...a[i,j1]...a[i,m]a[1,j]a[2,j]...a[i1,j]a[i+1,j]...a[n,j],现输入非负整形的矩阵A[n,m],求MAX(x[i,j]),即所有的x[i,j]中的最大值。

解析:

暴力肯定超时,我们预处理出两个方向的总体乘积,但是如果矩阵中有0,那么预处理出来的乘积就不对,因此,我们再遇到0的时候乘1,然后在预处理出每行每列有多少个0.

维护最大值时,如果发现某一行或某一列有两个以上的0,那么这个[i,j]就不用计算了,如果当前元素是0,且这一行和这一列只有一个0,那么就可以用这行的积乘这列的积再除以当前元素的平方来维护最大值.

由于事先不知道数据范围的大小,我又不想动态分配内存了,因此选用了STL中的vector.

代码:

#include <bits/stdc++.h>using namespace std;typedef long long LL;int main(){    int n, m;    while (cin >> n >> m) {        vector<vector<int> > matrix(n + 1, vector<int>(m + 1));        vector<vector<vector<LL> > > dp(2, vector<vector<LL> >(n + 1, vector<LL>(m + 1, 1)));        vector<int> x(n + 1, 0), y(m + 1, 0);        for (int i = 1; i <= n; i++) {            LL sum = 1;            for (int j = 1; j <= m; j++) {                int xx;                cin >> xx;                matrix[i][j] = xx;                if (!xx) {                    xx = 1;                    x[i]++;                    y[j]++;                }                dp[0][i][j] = dp[0][i][j] * (sum *= xx);            }            for (int j = 1; j <= m; j++) {                if (!matrix[i][j])                    dp[1][i][j] = dp[1][i - 1][j];                else                    dp[1][i][j] = dp[1][i - 1][j] * matrix[i][j];            }        }        LL ans = 0;        for (int i = 1; i <= n; i++) {            if (x[i] > 1)                continue;            for (int j = 1; j <= m; j++) {                if (!matrix[i][j] && y[j] > 1)                    continue;                LL tag = matrix[i][j] == 0 ? 1 : matrix[i][j];                ans = max(ans, dp[0][i][m] * dp[1][n][j] / (tag * tag));            }        }        cout << ans << endl;    }    return 0;}