提出 #75052257
ソースコード 拡げる
#include <atcoder/all>
#include <bits/stdc++.h>
using namespace std;
using namespace atcoder;
// 型・定数
using ll = long long;
const ll INFLL = 4e18;
const int INF = 2100000000;
const ll MOD = 1000000007;
using mint = modint1000000007; // 998244353 の場合は modint998244353 に変更
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};
// マクロ
#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define all(p) p.begin(), p.end()
#define yes cout << "Yes\n"
#define no cout << "No\n"
#define fi first
#define se second
// 優先度付きキュー(最小値取り出し)
template <class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
// 下限・上限探索
template <class T> int LB(const vector<T> &v, const T &a) {
return lower_bound(all(v), a) - v.begin();
}
template <class T> int UB(const vector<T> &v, const T &a) {
return upper_bound(all(v), a) - v.begin();
}
// 条件付き更新
template <class T> bool chmin(T &a, T b) {
if (b < a) {
a = b;
return true;
} else
return false;
}
template <class T> bool chmax(T &a, T b) {
if (a < b) {
a = b;
return true;
} else
return false;
}
// ソート
template <class T> void So(vector<T> &v) { sort(all(v)); }
template <class T> void Sore(vector<T> &v) { sort(all(v), greater<T>()); }
// Yes/No 出力
bool yneos(bool a, bool upp = false) {
cout << (a ? (upp ? "YES\n" : "Yes\n") : (upp ? "NO\n" : "No\n"));
return a;
}
// ベクタ系の補助関数
template <class T> void vec_out(const vector<T> &p, int ty = 0) {
if (ty == 2) {
cout << '{';
for (size_t i = 0; i < p.size(); i++) {
if (i)
cout << ",";
cout << '"' << p[i] << '"';
}
cout << "}\n";
} else {
if (ty == 1)
cout << p.size() << "\n";
for (size_t i = 0; i < p.size(); i++) {
if (i)
cout << " ";
cout << p[i];
}
cout << "\n";
}
}
template <class T> T vec_min(const vector<T> &a) {
assert(!a.empty());
T ans = a[0];
for (const auto &x : a)
chmin(ans, x);
return ans;
}
template <class T> T vec_max(const vector<T> &a) {
assert(!a.empty());
T ans = a[0];
for (const auto &x : a)
chmax(ans, x);
return ans;
}
template <class T> T vec_sum(const vector<T> &a) {
T ans = T(0);
for (const auto &x : a)
ans += x;
return ans;
}
template <class T> vector<T> cumsum(const vector<T> &v) {
vector<T> res(v.size() + 1, 0);
rep(i, 0, v.size()) res[i + 1] = res[i] + v[i];
return res;
}
int pop_count(ll a) { return __builtin_popcountll(a); }
template <class T> T square(T a) { return a * a; }
template <class T> vector<int> compress(vector<T> &v) {
vector<T> tmp = v;
sort(all(tmp));
tmp.erase(unique(all(tmp)), tmp.end());
vector<int> res(v.size());
rep(i, 0, v.size()) res[i] = LB(tmp, v[i]);
return res;
}
/* RollingHash (任意文字対応) */
// 使い方: RollingHash rh(s);
// rh.get(l, r): [l, r) のハッシュ値(pair)を取得
// rh.same(l1, r1, l2, r2): [l1, r1) と [l2, r2) が一致するか判定
struct RollingHash {
using ull = unsigned long long;
const ll base = 1007, mod1 = 1000000007, mod2 = 1000000009;
vector<ll> pow1, pow2, hash1, hash2;
RollingHash(const string &s) {
int n = s.size();
pow1.assign(n + 1, 1);
pow2.assign(n + 1, 1);
hash1.assign(n + 1, 0);
hash2.assign(n + 1, 0);
rep(i, 0, n) {
pow1[i + 1] = (pow1[i] * base) % mod1;
pow2[i + 1] = (pow2[i] * base) % mod2;
int c = (unsigned char)s[i];
hash1[i + 1] = (hash1[i] * base + c) % mod1;
hash2[i + 1] = (hash2[i] * base + c) % mod2;
}
}
pair<ll, ll> get(int l, int r) const {
ll x1 = (hash1[r] - hash1[l] * pow1[r - l]) % mod1,
x2 = (hash2[r] - hash2[l] * pow2[r - l]) % mod2;
if (x1 < 0)
x1 += mod1;
if (x2 < 0)
x2 += mod2;
return {x1, x2};
}
bool same(int l1, int r1, int l2, int r2) const {
return get(l1, r1) == get(l2, r2);
}
};
/* エラトステネスの篩 (O(1)素数判定, 高速素因数分解) */
// 使い方: Sieve si(n); (nは最大値)
// si.is_prime(x): xが素数か判定
// si.factorize(x): xの素因数を1次元配列で返す (例: 12 -> {2, 2, 3})
// si.factorize_pair(x): 素因数をpairで返す (例: 12 -> {{2, 2}, {3, 1}})
// si.count_distinct(x): 異なる素因数の個数 ω(x) を返す (例: 12 -> 2)
struct Sieve {
int max_n;
vector<int> spf;
Sieve(int n) : max_n(n), spf(n + 1) {
for (int i = 0; i <= n; i++)
spf[i] = i;
for (int i = 2; i * i <= n; i++)
if (spf[i] == i)
for (int j = i * i; j <= n; j += i)
if (spf[j] == j)
spf[j] = i;
}
vector<int> factorize(int n) {
vector<int> res;
while (n != 1) {
res.push_back(spf[n]);
n /= spf[n];
}
return res;
}
vector<pair<int, int>> factorize_pair(int n) {
vector<pair<int, int>> res;
while (n != 1) {
int p = spf[n];
int count = 0;
while (spf[n] == p) {
count++;
n /= p;
}
res.push_back({p, count});
}
return res;
}
bool is_prime(int n) {
if (n <= 1)
return false;
return spf[n] == n;
}
int count_distinct(int n) {
int cnt = 0;
while (n != 1) {
int p = spf[n];
cnt++;
while (spf[n] == p)
n /= p;
}
return cnt;
}
};
/* 約数全列挙 O(√N) / ソート済 */
vector<ll> get_divisors(ll n) {
vector<ll> res;
for (ll i = 1; i * i <= n; i++) {
if (n % i == 0) {
res.push_back(i);
if (i * i != n)
res.push_back(n / i);
}
}
sort(all(res));
return res;
}
/* 素因数分解 O(√N) */
vector<pair<ll, ll>> prime_factorize(ll n) {
vector<pair<ll, ll>> res;
for (ll a = 2; a * a <= n; a++) {
if (n % a != 0)
continue;
ll ex = 0;
while (n % a == 0) {
ex++;
n /= a;
}
res.push_back({a, ex});
}
if (n != 1)
res.push_back({n, 1});
return res;
}
/* LIS (最長増加部分列) O(N log N) / 復元可能 / 任意比較対応 */
// 使い方: LIS<T> lis;
// lis.build(v): LIS の長さを返す (デフォルトは狭義増加; strict=false で広義)
// lis.restore(): LIS の列を1つ返す
template <class T> struct LIS {
vector<T> dp;
vector<int> idx;
vector<int> prev_;
int build(const vector<T> &v, bool strict = true) {
int n = v.size();
dp.clear();
idx.resize(n);
prev_.assign(n, -1);
for (int i = 0; i < n; i++) {
int pos;
if (strict)
pos = lower_bound(dp.begin(), dp.end(), v[i]) - dp.begin();
else
pos = upper_bound(dp.begin(), dp.end(), v[i]) - dp.begin();
if (pos == (int)dp.size())
dp.push_back(v[i]);
else
dp[pos] = v[i];
idx[i] = pos;
}
return dp.size();
}
vector<T> restore(const vector<T> &v) {
int n = v.size(), len = dp.size(), cur = len - 1;
vector<T> res;
for (int i = n - 1; i >= 0 && cur >= 0; i--)
if (idx[i] == cur) {
res.push_back(v[i]);
cur--;
}
reverse(res.begin(), res.end());
return res;
}
};
/* bfs_farthest (木の直径など / 非再帰展開) */
// auto p1 = bfs_farthest(G, 0); // 頂点0から一番遠い点 {距離, 頂点}
// auto p2 = bfs_farthest(G, p1.second); // p1.secondから一番遠い点
// int diameter = p2.first; // それが木の直径!
pair<int, int> bfs_farthest(const vector<vector<int>> &G, int start) {
vector<int> dist(G.size(), -1);
queue<int> q;
q.push(start);
dist[start] = 0;
pair<int, int> res = {0, start};
while (!q.empty()) {
int v = q.front();
q.pop();
if (dist[v] > res.first)
res = {dist[v], v};
for (int to : G[v])
if (dist[to] == -1) {
dist[to] = dist[v] + 1;
q.push(to);
}
}
return res;
}
/* LCA (最小共通祖先) ダブリング */
// 使い方: LCA lc(G, 0); (0は根とする頂点)
// lc.get(u, v): uとvの最小共通祖先の頂点番号
// lc.dist(u, v): uとvの距離(エッジ数)
// lc.jump(v, k): 頂点vから親方向へk回遡った頂点(存在しなければ-1)
struct LCA {
int n, ln;
vector<vector<int>> parent;
vector<int> depth;
LCA(const vector<vector<int>> &G, int root = 0) {
n = G.size();
ln = 0;
while ((1 << ln) <= n)
ln++;
parent.assign(ln, vector<int>(n, -1));
depth.assign(n, 0);
init(G, root);
for (int k = 0; k + 1 < ln; k++)
for (int v = 0; v < n; v++)
if (parent[k][v] != -1)
parent[k + 1][v] = parent[k][parent[k][v]];
}
void init(const vector<vector<int>> &G, int root) {
queue<int> q;
q.push(root);
parent[0][root] = -1;
depth[root] = 0;
while (!q.empty()) {
int v = q.front();
q.pop();
for (auto to : G[v])
if (to != parent[0][v]) {
parent[0][to] = v;
depth[to] = depth[v] + 1;
q.push(to);
}
}
}
int get(int u, int v) {
if (depth[u] > depth[v])
swap(u, v);
for (int k = 0; k < ln; k++)
if ((depth[v] - depth[u]) >> k & 1)
v = parent[k][v];
if (u == v)
return u;
for (int k = ln - 1; k >= 0; k--)
if (parent[k][u] != parent[k][v]) {
u = parent[k][u];
v = parent[k][v];
}
return parent[0][u];
}
int dist(int u, int v) { return depth[u] + depth[v] - 2 * depth[get(u, v)]; }
int jump(int v, int k) {
for (int i = 0; i < ln; i++)
if (k >> i & 1) {
v = parent[i][v];
if (v == -1)
break;
}
return v;
}
};
/* 組み合わせ計算 */
const int MAX = 200000;
ll fact[MAX + 1], invfact[MAX + 1];
ll mod_pow(ll a, ll b) {
ll res = 1;
a %= MOD;
while (b) {
if (b & 1)
res = (res * a) % MOD;
a = (a * a) % MOD;
b >>= 1;
}
return res;
}
ll mod_inv(ll a) { return mod_pow(a, MOD - 2); }
void init_fact() {
fact[0] = 1;
rep(i, 1, MAX + 1) fact[i] = fact[i - 1] * i % MOD;
invfact[MAX] = mod_inv(fact[MAX]);
for (int i = MAX; i >= 1; i--)
invfact[i - 1] = invfact[i] * i % MOD;
}
ll nCr(int n, int r) {
if (r < 0 || r > n)
return 0;
return fact[n] * invfact[r] % MOD * invfact[n - r] % MOD;
}
// 差がk以上となるようにm個のボールを選ぶ方法は何通りか
// 結論から書くと、n-(k-1)*(m-1)Cm通りです。
// 最大公約数gcd・最小公倍数lcm
// ==========================================================
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
// ▼ ライブラリの初期化 (アンコメントして使用)
// dsu d(n); /* 1. dsu (UnionFind) */
// fenwick_tree<ll> fw(n); /* 2. BIT */
// mf_graph<ll> graph(n); /* 3. Dinic (最大流) */
// scc_graph g(n); /* 4. SCC (強連結成分分解) */
// lazy_segtree<S,op,e,F,mapping,comp,id> seg(n); /* 5. 遅延セグ木 */
// Sieve si(n); /* 6. エラトステネスの篩 */
// RollingHash rh(s); /* 7. ローリングハッシュ (要文字列s) */
// LCA lc(G, 0); /* 8. 最小共通祖先 (ダブリング) */
// init_fact(); /* 9. 組み合わせ計算 (nCr用事前計算) */
// vector<int> c_v = compress(v); /* 10. 座標圧縮 */
// LIS<int> lis; int len=lis.build(v); auto seq=lis.restore(v); /* 11. LIS */
int m; cin >> m;
vector<int> f(n);
rep(i, 0, n) cin >> f[i];
set<int> s(f.begin(), f.end());
yneos((int)s.size() == n);
yneos((int)s.size() == m);
return 0;
}
/*
【 AtCoder Library (ACL) 使い方メモ 】
1. dsu (UnionFind)
dsu d(n); // n頂点で初期化
d.merge(a, b); // aとbを結合
if (d.same(a, b)) // aとbが同じグループか判定
int s = d.size(a); // aが属するグループのサイズ
int l = d.leader(a); // aの親(代表元)を取得
2. fenwick_tree (BIT) ※0-indexed注意!
fenwick_tree<ll> fw(n); // 要素数nで初期化
fw.add(p, x); // p番目(0-indexed)にxを加算
ll s = fw.sum(l, r); // [l, r) の和を取得
3. segtree (セグメント木)
segtree<int, op, e> seg(n);
seg.set(p, x); // p番目をxに変更
int m = seg.prod(l, r); // [l, r) の結果を取得
// ▼ よく使う op と e の組み合わせ
// 【最大値】 int op(int a, int b) { return max(a, b); } / int e() { return
-1e9; }
// 【最小値】 int op(int a, int b) { return min(a, b); } / int e() { return
1e9; }
// 【区間和】 ll op(ll a, ll b) { return a + b; } / ll e() { return 0;
}
// 【 XOR 】 int op(int a, int b) { return a ^ b; } / int e() { return 0;
}
4. lazy_segtree (遅延評価セグメント木)
lazy_segtree<S, op, e, F, mapping, composition, id> seg(n);
seg.apply(l, r, x); // [l, r) 全体に魔法 x をかける
S m = seg.prod(l, r); // [l, r) の結果を取得
// ▼ よく使うパターンのコピペ用 (S=要素の型, F=魔法の型)
// 【① 区間加算・区間最大値】
// using S = ll; using F = ll;
// S op(S a, S b) { return max(a, b); } S e() { return -4e18; }
// S mapping(F f, S x) { return f + x; }
// F composition(F f, F g) { return f + g; }
// F id() { return 0; }
// 【② 区間加算・区間最小値】
// using S = ll; using F = ll;
// S op(S a, S b) { return min(a, b); } S e() { return 4e18; }
// S mapping(F f, S x) { return f + x; }
// F composition(F f, F g) { return f + g; }
// F id() { return 0; }
// 【③ 区間変更(置換)・区間最大値】 ※最小値の場合は op と e を変更
// using S = ll; using F = ll; const F ID = 8e18;
// S op(S a, S b) { return max(a, b); } S e() { return -4e18; }
// S mapping(F f, S x) { return (f == ID ? x : f); }
// F composition(F f, F g) { return (f == ID ? g : f); }
// F id() { return ID; }
5. scc_graph (強連結成分分解)
scc_graph g(n);
g.add_edge(u, v); // uからvへの有向辺
auto scc = g.scc(); //
トポロジカルソートされた二次元配列(グループごとの頂点リスト)が返る
6. mf_graph (最大流 / Dinic)
mf_graph<ll> graph(n);
graph.add_edge(from, to, cap); // 容量capの辺を張る (戻り値は辺ID)
ll f = graph.flow(start, goal); // startからgoalへの最大流量
7. modint (自動MOD演算)
using mint = modint1000000007; // または modint998244353
mint a = 10;
a += 1000000000; // 内部で勝手に % MOD される
cout << a.val(); // 出力時は .val() を付ける
8. LIS (最長増加部分列)
LIS<int> lis;
int len = lis.build(v); // LIS の長さ (狭義増加)
int len2 = lis.build(v, false); // LIS の長さ (広義増加)
auto seq = lis.restore(v); // LIS の列を1つ復元
// string にも対応: LIS<string> lis;
9. 座標圧縮 (compress)
vector<ll> A = {30, 10, 20, 20};
vector<int> B = compress(A);
// B: {2, 0, 1, 1} となる(圧縮後の値は 0-indexed)
*/
提出情報
| 提出日時 |
|
| 問題 |
B - Mapping |
| ユーザ |
Rsetu45 |
| 言語 |
C++23 (GCC 15.2.0) |
| 得点 |
200 |
| コード長 |
15693 Byte |
| 結果 |
AC |
| 実行時間 |
1 ms |
| メモリ |
3648 KiB |
ジャッジ結果
| セット名 |
Sample |
All |
| 得点 / 配点 |
0 / 0 |
200 / 200 |
| 結果 |
|
|
| セット名 |
テストケース |
| Sample |
00_sample_00.txt, 00_sample_01.txt, 00_sample_02.txt, 00_sample_03.txt |
| All |
00_sample_00.txt, 00_sample_01.txt, 00_sample_02.txt, 00_sample_03.txt, 01_random_1_00.txt, 01_random_1_01.txt, 01_random_1_02.txt, 02_random_2_00.txt, 02_random_2_01.txt, 02_random_2_02.txt, 03_random_3_00.txt, 03_random_3_01.txt, 03_random_3_02.txt, 04_random_4_00.txt, 04_random_4_01.txt, 04_random_4_02.txt, 04_random_4_03.txt, 04_random_4_04.txt, 04_random_4_05.txt |
| ケース名 |
結果 |
実行時間 |
メモリ |
| 00_sample_00.txt |
AC |
1 ms |
3488 KiB |
| 00_sample_01.txt |
AC |
1 ms |
3580 KiB |
| 00_sample_02.txt |
AC |
1 ms |
3596 KiB |
| 00_sample_03.txt |
AC |
1 ms |
3636 KiB |
| 01_random_1_00.txt |
AC |
1 ms |
3472 KiB |
| 01_random_1_01.txt |
AC |
1 ms |
3580 KiB |
| 01_random_1_02.txt |
AC |
1 ms |
3548 KiB |
| 02_random_2_00.txt |
AC |
1 ms |
3628 KiB |
| 02_random_2_01.txt |
AC |
1 ms |
3452 KiB |
| 02_random_2_02.txt |
AC |
1 ms |
3580 KiB |
| 03_random_3_00.txt |
AC |
1 ms |
3628 KiB |
| 03_random_3_01.txt |
AC |
1 ms |
3488 KiB |
| 03_random_3_02.txt |
AC |
1 ms |
3648 KiB |
| 04_random_4_00.txt |
AC |
1 ms |
3548 KiB |
| 04_random_4_01.txt |
AC |
1 ms |
3524 KiB |
| 04_random_4_02.txt |
AC |
1 ms |
3472 KiB |
| 04_random_4_03.txt |
AC |
1 ms |
3472 KiB |
| 04_random_4_04.txt |
AC |
1 ms |
3488 KiB |
| 04_random_4_05.txt |
AC |
1 ms |
3648 KiB |