結果
| 問題 |
No.2382 Amidakuji M
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-07-14 23:06:05 |
| 言語 | C++17(gcc12) (gcc 12.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 4,265 bytes |
| コンパイル時間 | 11,119 ms |
| コンパイル使用メモリ | 277,508 KB |
| 最終ジャッジ日時 | 2025-02-15 14:38:03 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 9 WA * 9 RE * 1 |
ソースコード
#line 2 "/home/cocojapanpan/Procon_CPP/proconLibrary/lib/template/procon.hpp"
#ifndef DEBUG
// 提出時にassertはオフ
#ifndef NDEBUG
#define NDEBUG
#endif
// 定数倍高速化
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#endif
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using i64 = long long;
using u64 = unsigned long long;
#define ALL(x) (x).begin(), (x).end()
template <class T>
using vec = vector<T>;
template <class T, class S>
inline bool chmax(T &a, const S &b) {
return (a < b ? a = b, 1 : 0);
}
template <class T, class S>
inline bool chmin(T &a, const S &b) {
return (a > b ? a = b, 1 : 0);
}
template <class T>
constexpr T INF = 1'000'000'000;
template <>
constexpr int INF<int> = 1'000'000'000;
template <>
constexpr ll INF<ll> = ll(INF<int>) * INF<int> * 2;
#line 3 "/home/cocojapanpan/Procon_CPP/proconLibrary/lib/data-structure/DualSegmentTree.hpp"
// 区間更新、一点取得を行う ただし作用は可換(RUQならタイムスタンプを付けるなどする)
// つまり区間更新を通常のセグ木の区間取得と同様に行う
template <class CommutativeMap>
class DualSegTree {
// CommutativeMap::S 要素の型
// CommutativeMap::F 作用の型
// CommutativeMap::mapping S(F f, S x) 要素xに作用fを作用させる
// CommutativeMap::id F() 恒等写像
// CommutativeMap::composition F(F f, F g) 作用の合成 可換!
using M = CommutativeMap;
using F = typename M::F;
using S = typename M::S;
static_assert(std::is_convertible_v<decltype(&M::mapping), std::function<S (F, S)>>, "mapping S(F, S) type error");
static_assert(std::is_convertible_v<decltype(&M::id), std::function<F()>>, "id F() type error");
static_assert(std::is_convertible_v<decltype(&M::composition), std::function<F (F, F)>>,
"composition F(F, F) type error");
public:
explicit DualSegTree(int _N, const S& init) : N(_N), data(_N, init) {
leaf = 1;
while(leaf < N) {
leaf <<= 1;
}
lazy.assign(leaf * 2, M::id());
}
// data[p] = x
void set(int p, const S& x) {
assert(0 <= p && p < N);
data[p] = x;
}
// 区間[l, r)に作用fを適用
void apply(int l, int r, const F & f) {
assert(0 <= l && l <= r && r <= N);
// logN個のlazyノードに分配
l += leaf; r += leaf;
while(l < r) {
if(l & 1) {
lazy[l] = M::composition(lazy[l], f);
++l;
}
if(r & 1) {
--r;
lazy[r] = M::composition(lazy[r], f);
}
l >>= 1;
r >>= 1;
}
}
// a[p]を取得 上のノードlogN個を作用させて返す
S get(int p) const {
assert(0 <= p && p < N);
int index = p + leaf;
F fmap = M::id();
while(index > 0) {
fmap = M::composition(fmap, lazy[index]);
index >>= 1;
}
return M::mapping(fmap, data[p]);
}
private:
const int N; // 考える要素数
vec<F> lazy; // 可換な写像の完全二分木
vec<S> data; // 実際の値
int leaf; // 葉の数
};
#line 3 "main.cpp"
struct rangeAddOne {
using S = int;
using F = int;
static S mapping(F f, S x) {
return f + x;
}
static F id() {
return 0;
}
static F composition(F f, F g) {
return f + g;
}
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int N;
ll M;
cin >> N >> M;
vec<int> P(N);
for(int &p : P) {
cin >> p;
--p;
}
DualSegTree<rangeAddOne> dual(N, 0);
// まず最小の回数を数える
ll cnt = 0;
for(int i = 0; i < N; i++) {
cnt += dual.get(P[i]) + (P[i] - i);
dual.apply(i, dual.get(P[i]) + P[i] + 1, 1);
}
ll ans = -1;
if(cnt == 0) {
ans = 0;
} else {
ll smallestM = (cnt + M - 1) / M * M;
if((smallestM - cnt) % 2 == 0) {
ans = smallestM;
} else if((smallestM + M - cnt) % 2 == 0) {
ans = smallestM + M;
}
}
cout << ans << "\n";
}