1. 程式人生 > 實用技巧 >【Atcoder Beginner Contest 178】E-F

【Atcoder Beginner Contest 178】E-F

Atcoder Beginner Contest 178 E,F 題解

E - Dist Max

題意

給出 n 個點的座標(座標均為整數),求出曼哈頓距離最大的兩個點的距離,兩個點的曼哈頓距離為\(|x_1-x_2|+|y_1-y_2|\)

題解

這道題又讓我想起來,我之前說過的一句話,看到題目中給出公式,一定要化簡試試。愣是沒有想起來

去掉曼哈頓距離中的絕對值符號,4種情況:

  1. \(x_1-x_2+y_1-y_2 = (x_1+y_1)-(y_1+y_2)\)
  2. \(x_2-x_1+y_1-y_2=(x_2-y_2) - (x_1-y_1)\)
  3. \(x_1-y_1+y_2-y_1=(x_1-y_1)-(x_2-y_2)\)
  4. \(x_2-x_1+y_2-y_1=(x_2+y_2)-(x_1+y_1)\)

第 1 種情況和第 4 種情況一樣
第 2 種情況和第 3 種情況一樣

所以答案一定在 3,4 中產生。

我們只需要求出\(x+y\)的最大值、最小值,\(x-y\)的最大值、最小值。

輸出較大的差值即可。

程式碼

/*
 * @Autor: valk
 * @Date: 2020-04-04 14:56:12
 * @LastEditTime: 2020-09-17 20:07:08
 * @Description: 如果邪惡  是華麗殘酷的樂章 它的終場 我會親手寫上 晨曦的光 風乾最後一行憂傷 黑色的墨 染上安詳
 */
 
#include <algorithm>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll mod = 1e9 + 7;
const ll seed = 12289;
const double eps = 1e-6;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int N = 2e3 + 10;
 
int main()
{
    int n;
    scanf("%d", &n);
    ll maxn1 = -inf, maxn2 = -inf, minn1 = inf, minn2 = inf;
    for (ll i = 1; i <= n; i++) {
        ll x, y;
        scanf("%lld%lld", &x, &y);
        ll sum = x + y;
        ll dis = x - y;
        maxn1 = max(maxn1, sum);
        minn1 = min(minn1, sum);
        maxn2 = max(maxn2, dis);
        minn2 = min(minn2, dis);
    }
    printf("%lld\n", max(maxn1 - minn1, maxn2 - minn2));
    return 0;
}

F - Contrast

題意

給定兩個長度相同,都按照升序排序的序列 a ,b ,問是否可以通過重排第二個序列,使得對於任意 \(i\) ,\(a_i!=b_i\)

思路

剛開始,直接把 b 序列放到 set 中,每次取出最大的和當前 a 序列的值比較,如果不相等,這個值就放到當前位置。否則取前一個,如果當前是 set 的開頭,那麼就不可能滿足題目要求。

後來一想可以通過和前面的交換一下來使這個滿足。但是用什麼如何找到前面符合標準的是個問題,怎麼寫複雜度都達不到。

看題解之後,恍然大悟。

題解首先是把 b 序列整個翻轉過來,一一匹配,中間可能有一段區間\([l,r]\) a 序列和 b 序列相同,並且都是一個數字,那麼這些位置就和其他位置交換,思路看著倒是差不多,但是這個很騷。交換的時候只需要判斷不是區間 \([l,r]\)

的位置即可。

程式碼

/*
 * @Autor: valk
 * @Date: 2020-07-17 16:50:40
 * @LastEditTime: 2020-09-19 17:27:22
 * @Description: 如果邪惡  是華麗殘酷的樂章 它的終場 我會親手寫上 晨曦的光 風乾最後一行憂傷 黑色的墨 染上安詳
 */
 
#include <algorithm>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int mod = 1e9 + 7;
const int seed = 12289;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;
 
int arr[N], brr[N];
 
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &arr[i]);
    }
    for (int i = 1; i <= n; i++) {
        scanf("%d", &brr[n - i + 1]);
    }
    int pos = 1, flag = 1;
    for (int i = 1; i <= n; i++) {
        if (arr[i] == brr[i]) {
            while (pos <= n && (arr[i] == brr[pos] || arr[i] == arr[pos])) {
                pos++;
            }
            if (pos > n) {
                flag = 0;
                break;
            }
            swap(brr[pos], brr[i]);
        }
    }
    if (!flag) {
        printf("No\n");
    } else {
        printf("Yes\n");
        for (int i = 1; i <= n; i++) {
            printf("%d ", brr[i]);
        }
        printf("\n");
    }
    return 0;
}