結果
| 問題 |
No.1779 Magical Swap
|
| コンテスト | |
| ユーザー |
nanophoto12
|
| 提出日時 | 2021-12-12 11:24:32 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 256 ms / 2,000 ms |
| コード長 | 4,354 bytes |
| コンパイル時間 | 4,301 ms |
| コンパイル使用メモリ | 263,512 KB |
| 最終ジャッジ日時 | 2025-01-26 09:03:38 |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 18 |
ソースコード
#include <bits/stdc++.h>
#define M_PI 3.14159265358979323846 // pi
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;
typedef tuple<ll, ll, ll> t3;
typedef tuple<ll, ll, ll, ll> t4;
typedef tuple<ll, ll, ll, ll, ll> t5;
#define rep(a,n) for(ll a = 0;a < n;a++)
template<typename T>
static inline void chmin(T& ref, const T value) {
if (ref > value) ref = value;
}
template<typename T>
static inline void chmax(T& ref, const T value) {
if (ref < value) ref = value;
}
#include <atcoder/all>
using namespace atcoder;
typedef modint998244353 mint;
typedef ll CHT_TYPE;
class ConvexHullTrickDynamic {
private:
// 直線 **************************************************************
struct Line {
CHT_TYPE a, b; // y = ax + b
mutable std::function<const Line* ()> getSuc; // 次の直線へのポインタ (ソートで用いる)
bool operator<(const Line& rhs) const {
// 取得クエリでは次の直線との差分でソート
if (rhs.b == IS_QUERY) {
const Line* suc = getSuc();
if (suc == nullptr) return false;
const CHT_TYPE& x = rhs.a;
return (suc->a - a) * x + suc->b - b > 0;
}
if (b == IS_QUERY) {
const Line* suc = rhs.getSuc();
if (suc == nullptr) return true;
const CHT_TYPE& x = a;
return (suc->a - rhs.a) * x + suc->b - rhs.b < 0;
}
// 通常の直線どうしは傾きソート
return a < rhs.a;
}
};
// 直線集合 **********************************************************
class LinesSet {
private:
// true -> 最小値クエリ, false -> 最大値クエリ
bool flagMin;
std::multiset<Line> lines;
public:
// コンストラクタ ( 第一引数falseで最大値クエリ,デフォルトで最小値クエリ )
LinesSet(bool flagMin = true) : flagMin(flagMin) {};
// 直線lが不必要であるかどうか
bool isBad(std::multiset<Line>::iterator l) {
const auto&& nel = std::next(l);
if (l == lines.begin()) { // lが傾き最小のとき
if (nel == lines.end()) return false; // lしかないなら必要
return l->a == nel->a && l->b <= nel->b;
}
else {
const auto&& prl = std::prev(l);
if (nel == lines.end()) return l->a == prl->a && l->b <= prl->b;
return (prl->b - l->b) * (nel->a - l->a) >= (nel->b - l->b) * (prl->a - l->a);
}
}
// 直線y=ax+bを追加する
inline void add(CHT_TYPE a, CHT_TYPE b) {
if (flagMin) a = -a, b = -b;
auto&& it = lines.insert(Line{ a, b });
it->getSuc = [=] { return (std::next(it) == lines.end() ? nullptr : &*std::next(it)); };
if (isBad(it)) { lines.erase(it); return; }
while (std::next(it) != lines.end() && isBad(std::next(it))) lines.erase(std::next(it));
while (it != lines.begin() && isBad(std::prev(it))) lines.erase(std::prev(it));
}
// 直線群の中でxの時に最小(最大)となる値を返す
inline CHT_TYPE get(CHT_TYPE x) {
auto&& l = *lines.lower_bound(Line{ x, IS_QUERY });
if (flagMin) return -l.a * x - l.b;
else return l.a * x + l.b;
}
};
static const CHT_TYPE IS_QUERY = std::numeric_limits<CHT_TYPE>::lowest();
LinesSet linesSet;
public:
// コンストラクタ ( 第一引数falseで最大値クエリ,デフォルトで最小値クエリ )
ConvexHullTrickDynamic(bool flagMin = true) : linesSet(flagMin) {}
// 直線y=ax+bを追加する
inline void add(CHT_TYPE a, CHT_TYPE b) { linesSet.add(a, b); }
// あるxのときの直線集合での最小値を求める
inline CHT_TYPE get(CHT_TYPE x) { return linesSet.get(x); }
};
int main() {
ll t;
cin >> t;
rep(_, t) {
ll n;
cin >> n;
vector<ll> as(n + 1, 0), bs(n + 1, 0);
rep(i, n) {
cin >> as[i + 1];
}
rep(i, n) {
cin >> bs[i + 1];
}
atcoder::dsu tree(n + 1);
for (int i = 2; i <= n; i++) {
for (int j = 1; i * j <= n; j++) {
tree.merge(i, i* j);
}
}
vector<vector<ll>> ag, bg;
bool ok = true;
for(auto& x : tree.groups()){
ag.emplace_back();
bg.emplace_back();
for (auto y : x) {
ag.back().emplace_back(as[y]);
bg.back().emplace_back(bs[y]);
}
sort(ag.back().begin(), ag.back().end());
sort(bg.back().begin(), bg.back().end());
if (ag.back() != bg.back()) {
ok = false;
break;
}
}
if (ok) {
cout << "Yes" << endl;
}
else {
cout << "No" << endl;
}
}
return 0;
}
nanophoto12