AcWing-5132. 奶牛照相+5133. 奶牛排队

5132.奶牛照相

对于第i个奶牛:
宽:用总宽减去当前奶牛的宽
高:如果是最高的那个奶牛,则此时为全部奶牛中高度排名第二的那个值;如果不是最高的那个,则此时为全部奶牛中高度排名第一的那个值
输出:宽*高

#include 
using namespace std;
#define ll long long
#define sf(x) scanf("%d", &x);
#define de(x) cout << x << " ";
#define Pu puts("");
const int N = 5e5 + 10;
int n, m, ans;
int w[N], h[N];
// priority_queueq;
int fi, se;
int main() {
    cin >> n;
    ll sz = 0;
    // fi=se=0;
    for (int i = 0; i < n; i++) {
        sf(w[i]) sf(h[i]);
        sz += w[i];
        // q.push(h[i]);
    }
    // sort(h,h+n);
    int mn = 0;  // 找最高奶牛对应的下标
    for (int i = 0; i < n; i++) {
        if (h[i] > mn) {
            mn = h[i];
            fi = i;
        }
    }
    mn = 0;  // 找第二高奶牛对应的下标
    for (int i = 0; i < n; i++) {
        if (i == fi)
            continue;
        if (h[i] > mn) {
            mn = h[i];
            se = i;
        }
    }
    ll t;
    for (int i = 0; i < n; i++) {
        if (i == fi) {
            // de(sz - w[i]) de(h[se]) Pu;
            t = (sz - w[i]) * h[se];
        } else {
            t = (sz - w[i]) * h[fi];
        }
        printf("%lld ", t);
    }
    return 0;
}

5133. 奶牛排队

第一思路是使用树:左子代表前一个,右子代表后一个。
但是后来发现不行:按照这样处理会出现很多个"小树",无法汇聚
因为题目最后要求是一个序列,这样的话,建树就没有了思路

尝试了几个样例后发现,每行输入后形成一个三个点的小片段:中间未知,前后两个点已知
那么可以用结构体记录每行输入的两个点,并记录他们的关系。(结构体中有l和r两个变量)
那么u[i].l表示标号为i的节点的前一个点的标号为l
u[i].r表示标号为i的节点的后一个点的标号为r

这样处理每一行的输入后,最终一定是会形成两个队伍
而其中一个队伍的头节点一定是输入含有0的那一行(左边为0)的非0点
另外一个队伍可以查找出来。(我使用的是一个数组,只要找到了另外一个队伍中的任意一个点
可以使用一个while循环找出最左边的点)
交替输出即可

#include 
using namespace std;
#define ll long long
#define sf(x) scanf("%d", &x);
#define de(x) cout << x << " ";
#define Pu puts("");
const int N = 1e6 + 10;
int n, m, ans;
struct e {
    int l, r;
} u[N];
int vis[N];  // 标记数组,以便于找另外一个队伍
int val[N];  // 最终的结果(两个队列中的交替值)
int main() {
    cin >> n;
    int x, y;
    int fi;
    for (int i = 0; i < n; i++) {
        sf(x) sf(y);
        vis[x] = 1;  // 标记
        vis[y] = 1;

        u[x].r = y;
        u[y].l = x;  // 存储相互关系

        if (x == 0)
            fi = y;  // 最终队列中的第二个
    }
    for (int i = fi; i; i = u[i].r) {
        vis[i] = 2;  // 标记属于含有第二个的那一队
    }
    // 接下来找另外一队的头
    int se;
    for (int i = 1; i <= 1e6; i++) {
        if (vis[i] == 1) {
            int id = i;  // 已经找到了另外一队的成员
            // 那么一直向左,找到队伍的头
            while (u[id].l) {
                id = u[id].l;
            }
            se = id;
            break;
        }
    }

    // 两个队交替出现
    bool flag = true;
    for (int i = 0; i < n; i++) {
        if (flag == true) {
            val[i] = se;
            se = u[se].r;
            flag = false;
        } else {
            val[i] = fi;
            fi = u[fi].r;
            flag = true;
        }
    }
    for (int i = 0; i < n; i++) {
        de(val[i]);
    }  // 输出

    return 0;
}

你可能感兴趣的:(AcWing,刷题+算法,#,思维+模拟,算法,图论)