結果
| 問題 | 
                            No.1698 Face to Face
                             | 
                    
| コンテスト | |
| ユーザー | 
                             | 
                    
| 提出日時 | 2025-05-27 17:20:12 | 
| 言語 | C++17  (gcc 13.3.0 + boost 1.87.0)  | 
                    
| 結果 | 
                             
                                AC
                                 
                             
                            
                         | 
                    
| 実行時間 | 733 ms / 5,000 ms | 
| コード長 | 3,923 bytes | 
| コンパイル時間 | 1,012 ms | 
| コンパイル使用メモリ | 57,348 KB | 
| 実行使用メモリ | 36,780 KB | 
| 最終ジャッジ日時 | 2025-05-27 17:20:36 | 
| 合計ジャッジ時間 | 17,631 ms | 
| 
                            ジャッジサーバーID (参考情報)  | 
                        judge4 / judge3 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| sample | AC * 3 | 
| other | AC * 45 | 
コンパイルメッセージ
main.cpp: In function ‘int main()’:
main.cpp:161:10: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  161 |     scanf("%d", &n);
      |     ~~~~~^~~~~~~~~~
main.cpp:164:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  164 |         scanf("%d", &a[i]);
      |         ~~~~~^~~~~~~~~~~~~
main.cpp:169:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  169 |         scanf("%d", &b[i]);
      |         ~~~~~^~~~~~~~~~~~~
main.cpp:174:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  174 |         scanf("%d", &p[i]);
      |         ~~~~~^~~~~~~~~~~~~
            
            ソースコード
#include <set>
#include <cstdio>
constexpr int MAX_N = 100000 + 2;
constexpr int MAX_LOG_N = 16 + 2;
int n, ans, pA[MAX_N], pB[MAX_N];
int p[MAX_N], a[MAX_N], b[MAX_N];
bool validA[MAX_N], validB[MAX_N];
std::set<std::pair<int, int>> A, B;
struct Node {
    int ls, rs, cnt;
};
class SegmentTree {
  public:
    int nodeId, rt[MAX_N];
    Node t[MAX_N * MAX_LOG_N];
    void insert(int &o1, int o2, int l, int r, int x) {
        t[o1 = ++nodeId] = t[o2];
        t[o1].cnt++;
        if (l == r) {
            return;
        }
        int mid = (l + r) >> 1;
        if (x <= mid) {
            insert(t[o1].ls, t[o2].ls, l, mid, x);
        } else {
            insert(t[o1].rs, t[o2].rs, mid + 1, r, x);
        }
    }
    void insert(int x, int v) {
        insert(rt[x], rt[x - 1], 1, n, v);
    }
    int query(int o, int l, int r, int x, int y) {
        if (!o) {
            return 0;
        }
        if (x <= l && r <= y) {
            return t[o].cnt;
        }
        int mid = (l + r) >> 1;
        if (y <= mid) {
            return query(t[o].ls, l, mid, x, y);
        }
        if (x > mid) {
            return query(t[o].rs, mid + 1, r, x, y);
        }
        return query(t[o].ls, l, mid, x, y)
          + query(t[o].rs, mid + 1, r, x, y);
    }
    int query(int L, int R, int l, int r) {
        return l > r ? 0 :
          query(rt[R], 1, n, l, r) -
          query(rt[L - 1], 1, n, l, r);
    }
} segTree;
int calcA(int l, int r) {
    auto pre = --B.lower_bound({l + 1, 0});
    int ret = segTree.query(l, r, pre->first, pre->second);
    if (pre->second >= r) {
        return ret;
    }
    ret = std::min(ret, pre->second - l + 1);
    auto suf = --B.lower_bound({r + 1, 0});
    ret += segTree.query(l, r,
      pre->second + 1, suf->first - 1);
    ret += std::min(
      r - suf->first + 1,
      segTree.query(l, r, suf->first, suf->second)
    );
    return ret;
}
int calcB(int l, int r) {
    auto pre = --A.lower_bound({l + 1, 0});
    int ret = segTree.query(pre->first, pre->second, l, r);
    if (pre->second >= r) {
        return ret;
    }
    ret = std::min(ret, pre->second - l + 1);
    auto suf = --A.lower_bound({r + 1, 0});
    ret += segTree.query(
      pre->second + 1, suf->first - 1, l, r
    );
    ret += std::min(
      r - suf->first + 1,
      segTree.query(suf->first, suf->second, l, r)
    );
    return ret;
}
void updateA(int x) {
    auto it = A.lower_bound({x, x});
    auto pre = it, suf = it;
    int l = x, r = x;
    if (validA[x - 1]) {
        ans -= calcA(l = (--pre)->first, x - 1);
        A.erase(pre);
    }
    if (validA[x + 1]) {
        ans -= calcA(x + 1, r = (++suf)->second);
        A.erase(suf);
    }
    ans -= calcA(x, x);
    A.erase(it);
    ans += calcA(l, r);
    A.insert({l, r});
}
void updateB(int x) {
    auto it = B.lower_bound({x, x});
    auto pre = it, suf = it;
    int l = x, r = x;
    if (validB[x - 1]) {
        ans -= calcB(l = (--pre)->first, x - 1);
        B.erase(pre);
    }
    if (validB[x + 1]) {
        ans -= calcB(x + 1, r = (++suf)->second);
        B.erase(suf);
    }
    ans -= calcB(x, x);
    B.erase(it);
    ans += calcB(l, r);
    B.insert({l, r});
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        pA[a[i]] = i;
    }
    for (int i = 1; i <= n; i++) {
        scanf("%d", &b[i]);
        pB[b[i]] = i;
    }
    for (int i = 1; i <= n; i++) {
        scanf("%d", &p[i]);
    }
    for (int i = 1; i <= n; i++) {
        a[i] = pB[p[a[i]]];
        ans += a[i] == i;
    }
    for (int i = 1; i <= n; i++) {
        segTree.insert(i, a[i]);
        A.insert({i, i});
        B.insert({i, i});
    }
    for (int i = 1; i <= n; i++) {
        validA[pA[i]] = validB[pB[i]] = true;
        updateA(pA[i]);
        updateB(pB[i]);
        printf("%d\n", ans);
    }
    return 0;
}