結果
| 問題 |
No.1028 闇討ち
|
| コンテスト | |
| ユーザー |
kaage
|
| 提出日時 | 2020-04-17 21:57:47 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 868 ms / 2,000 ms |
| コード長 | 20,725 bytes |
| コンパイル時間 | 3,380 ms |
| コンパイル使用メモリ | 165,160 KB |
| 実行使用メモリ | 25,136 KB |
| 最終ジャッジ日時 | 2024-11-14 22:20:07 |
| 合計ジャッジ時間 | 12,140 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 20 |
ソースコード
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC target("avx")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#define rep(i, n) for(int i=0;i<(n);i++)
#define REP(i, n) for(int i=1;i<=(n);i++)
#define all(V) V.begin(),V.end()
typedef long long lint;
typedef std::pair<lint, lint> P;
constexpr int INF = INT_MAX;
constexpr lint LINF = LLONG_MAX;
constexpr double eps = 1e-9;
template<class T>
class prique :std::priority_queue<T, std::vector<T>, std::greater<T>> {};
using namespace std;
template<class T, class Alloc = std::allocator<T>>
class Vector {
using traits = std::allocator_traits<Alloc>;
using size_type = unsigned int;
class iterator {
public:
using difference_type = int;
using value_type = T;
using pointer = T*;
using reference = T&;
using iterator_category = std::random_access_iterator_tag;
private:
T* p;
public:
iterator()noexcept :p(nullptr) {}
iterator(Vector* base, difference_type index) noexcept :p(base->e + index) {}
iterator(const iterator& i) :p(i.p) {}
iterator& operator=(const iterator& i) = default;
iterator& operator++() {
p++;
return *this;
}
iterator operator++(int) {
iterator res = *this;
p++;
return res;
}
iterator operator+(const difference_type& x)const {
return iterator(*this) += x;
}
iterator& operator+=(const difference_type& x) {
p += x;
return *this;
}
iterator& operator--() {
p--;
return *this;
}
iterator operator--(int) {
iterator res = *this;
p--;
return res;
}
iterator operator-(const difference_type& x)const {
return iterator(*this) -= x;
}
difference_type operator-(const iterator& i)const {
return p - i.p;
}
iterator& operator-=(const difference_type& x) {
p -= x;
return *this;
}
reference operator*()const {
return *p;
}
reference operator[](const difference_type& x)const {
return *(p + x);
}
bool operator<(const iterator& i)const {
return p < i.p;
}
bool operator<=(const iterator& i)const {
return p <= i.p;
}
bool operator==(const iterator& i)const {
return p == i.p;
}
bool operator>(const iterator& i)const {
return p > i.p;
}
bool operator>=(const iterator& i)const {
return p >= i.p;
}
bool operator!=(const iterator& i)const {
return p != i.p;
}
};
class const_iterator {
public:
using difference_type = int;
using value_type = T;
using pointer = const T*;
using reference = const T&;
using iterator_category = std::random_access_iterator_tag;
private:
const T* p;
public:
const_iterator()noexcept :p(nullptr) {}
const_iterator(Vector* base, difference_type index) noexcept :p(base->e + index) {}
const_iterator(const iterator& i) :p(i.p) {}
const_iterator(const const_iterator& i) :p(i.p) {}
const_iterator& operator=(const const_iterator& i) = default;
const_iterator& operator++() {
p++;
return *this;
}
const_iterator operator++(int) {
const_iterator res = *this;
p++;
return res;
}
const_iterator operator+(const difference_type& x)const {
return const_iterator(*this) += x;
}
const_iterator& operator+=(const difference_type& x) {
p += x;
return *this;
}
const_iterator& operator--() {
p--;
return *this;
}
const_iterator operator--(int) {
const_iterator res = *this;
p--;
return res;
}
const_iterator operator-(const difference_type& x)const {
return const_iterator(*this) -= x;
}
difference_type operator-(const const_iterator& i)const {
return p - i.p;
}
const_iterator& operator-=(const difference_type& x) {
p -= x;
return *this;
}
reference operator*()const {
return *p;
}
reference operator[](const difference_type& x)const {
return *(p + x);
}
bool operator<(const const_iterator& i)const {
return p < i.p;
}
bool operator<=(const const_iterator& i)const {
return p <= i.p;
}
bool operator==(const const_iterator& i)const {
return p == i.p;
}
bool operator>(const const_iterator& i)const {
return p > i.p;
}
bool operator>=(const const_iterator& i)const {
return p >= i.p;
}
bool operator!=(const const_iterator& i)const {
return p != i.p;
}
};
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
private:
T* e;
unsigned int length = 0, cap = 1;
Alloc alloc;
static_assert(std::is_same<T, typename Alloc::value_type>::value, "The allocator value type is not matched the vector value type.");
static_assert(!std::is_const<T>::value, "This library forbids containers of const elements");
public:
Vector() :Vector(Alloc()) {}
explicit Vector(const Alloc& a) :alloc(a) {
e = alloc.allocate(cap);
}
explicit Vector(size_type n, const Alloc& a = Alloc()) :alloc(a) {
while (cap < n)cap *= 2;
e = alloc.allocate(cap);
rep(i, n)emplace_back();
}
explicit Vector(size_type n, const T& value, const Alloc& a = Alloc()) :alloc(a) {
while (cap < n)cap *= 2;
e = alloc.allocate(cap);
rep(i, n)emplace_back(value);
}
template<class InputIter>
Vector(InputIter first, InputIter last, const Alloc& a = Alloc()) :alloc(a) {
e = alloc.allocate(cap);
for (InputIter i = first; i != last; i++) {
emplace_back(*i);
}
}
Vector(const Vector& x, const Alloc& a = Alloc()) :alloc(a) {
while (cap < x.length)cap *= 2;
length = x.length;
e = alloc.allocate(cap);
rep(i, x.length)traits::construct(alloc, e + i, *(x.e + i));
}
Vector(Vector&& x, const Alloc& a = Alloc()) :alloc(a) {
cap = x.cap;
length = x.length;
e = x.e;
x.e = nullptr;
}
~Vector() {
if (e != nullptr) {
rep(i, length)traits::destroy(alloc, e + i);
alloc.deallocate(e, cap);
}
}
Vector& operator=(const Vector& x) {
rep(i, length)traits::destroy(alloc, e + i);
alloc.deallocate(e, cap);
length = x.length;
cap = 1;
while (cap < length)cap *= 2;
e = alloc.allocate(cap);
rep(i, length)traits::construct(alloc, e + i, *(x.e + i));
return *this;
}
Vector& operator=(Vector&& x) {
rep(i, length)traits::destroy(alloc, e + i);
alloc.deallocate(e, cap);
cap = x.cap;
length = x.length;
e = x.e;
x.e = nullptr;
return *this;
}
private:
void extension() {
T* e_ = alloc.allocate(cap * 2);
rep(i, length)traits::construct(alloc, e_ + i, *(e + i));
rep(i, length)traits::destroy(alloc, e + i);
alloc.deallocate(e, cap);
e = e_;
cap *= 2;
}
void extension(size_type n) {
unsigned int r = 1;
while (cap * r < n)r *= 2;
if (r == 1)return;
T* e_ = alloc.allocate(cap * r);
rep(i, length)traits::construct(alloc, e_ + i, *(e + i));
rep(i, length)traits::destroy(alloc, e + i);
alloc.deallocate(e, cap);
e = e_;
cap *= r;
}
public:
template<class InputIter>
void assign(InputIter first, InputIter last) {
unsigned int cnt = 0;
for (InputIter i = first; i != last; i++) {
if (cnt == cap) {
length = std::max(length, cnt);
extension();
}
traits::construct(alloc, e + cnt, *i);
cnt++;
}
}
void assign(size_type n, const T& value) {
extension(n);
std::fill(e, e + n, value);
}
template<class... Args>
void emplace_back(Args&&... args) {
if (length == cap)extension();
traits::construct(alloc, e + length, std::forward<Args>(args)...);
length++;
}
void push_back(const T& value) {
emplace_back(value);
}
void push_back(T&& value) {
emplace_back(std::move(value));
}
void pop_back() {
traits::destroy(alloc, e + length);
length--;
}
iterator erase(iterator pos) {
const iterator res = pos;
iterator t = pos; t++;
for (iterator i = pos; t != end(); i++, t++) {
*i = std::move(*t);
}
pop_back();
return res;
}
iterator erase(iterator first, iterator last) {
const iterator res = first;
typename iterator::difference_type d = last - first;
for (iterator i = first; i + d != end(); i++) {
*i = std::move(*(i + d));
}
rep(i, d)pop_back();
return res;
}
void swap(Vector& x) {
std::swap(length, x.length);
std::swap(cap, x.cap);
std::swap(e, x.e);
}
void clear() {
while (length)pop_back();
}
size_type size()const {
return length;
}
void resize(size_type n, const T& value = T()) {
extension(n);
while (n < length)pop_back();
std::fill(e, e + n, value);
}
size_type capacity()const {
return cap;
}
bool empty()const {
return !length;
}
T& operator[](const unsigned int pos) {
return e[pos];
}
T* data() {
return e;
}
T& front() {
return *e;
}
T& back() {
return *(e + length - 1);
}
iterator begin() noexcept {
return iterator(this, 0);
}
const_iterator begin()const noexcept {
return const_iterator(this, 0);
}
const_iterator cbegin()const noexcept {
return const_iterator(this, 0);
}
iterator rbegin()noexcept {
return reverse_iterator(this, 0);
}
const_iterator rbegin()const noexcept {
return const_reverse_iterator(this, 0);
}
const_iterator crbegin()const noexcept {
return const_reverse_iterator(this, 0);
}
iterator end() noexcept {
return iterator(this, length);
}
const_iterator end()const noexcept {
return const_iterator(this, length);
}
const_iterator cend()const noexcept {
return const_iterator(this, length);
}
iterator rend()noexcept {
return reverse_iterator(this, length);
}
const_iterator rend()const noexcept {
return const_reverse_iterator(this, length);
}
const_iterator crend()const noexcept {
return const_reverse_iterator(this, length);
}
};
template <class T, class U>
inline bool chmax(T& lhs, const U& rhs) {
if (lhs < rhs) {
lhs = rhs;
return 1;
}
return 0;
}
template <class T, class U>
inline bool chmin(T& lhs, const U& rhs) {
if (lhs > rhs) {
lhs = rhs;
return 1;
}
return 0;
}
inline lint gcd(lint a, lint b) {
while (b) {
lint c = a;
a = b; b = c % b;
}
return a;
}
inline lint lcm(lint a, lint b) {
return a / gcd(a, b) * b;
}
bool isprime(lint n) {
if (n == 1)return false;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0)return false;
}
return true;
}
lint mypow(lint a, lint b) {
if (!b)return 1;
if (b & 1)return mypow(a, b - 1) * a;
lint memo = mypow(a, b >> 1);
return memo * memo;
}
lint modpow(lint a, lint b, lint m) {
if (!b)return 1;
if (b & 1)return modpow(a, b - 1, m) * a % m;
lint memo = modpow(a, b >> 1, m);
return memo * memo % m;
}
template<typename T>
void printArray(std::vector<T>& vec) {
rep(i, vec.size() - 1)std::cout << vec[i] << " ";
std::cout << vec.back() << std::endl;
}
template<typename T>
void printArray(Vector<T>& vec) {
rep(i, vec.size() - 1)std::cout << vec[i] << " ";
std::cout << vec.back() << std::endl;
}
template<typename T>
void printArray(T l, T r) {
T rprev = r;
rprev--;
for (T i = l; i != rprev; i++) {
std::cout << *i << " ";
}
std::cout << *rprev << std::endl;
}
std::string to_string(Vector<int>& vec) {
std::string res = "[";
rep(i, vec.size() - 1)res += std::to_string(vec[i]) + ", ";
res += std::to_string(vec.back()) + "]";
return res;
}
template<typename T, typename U>
class SegTree {
protected:
int n = 1, rank = 0;
vector<T> node;
vector<U> lazy;
vector<bool> lazyflag;
vector<int> width;
virtual void lazyf(U&, const U&) = 0;
virtual void updf(T&, const U&, const unsigned int&) = 0;
void eval(int k) {
if (!k)return;
for (int i = rank; i > 0; i--) {
int nk = k >> i;
if (lazyflag[nk]) {
updf(node[2 * nk], lazy[nk], width[2 * nk]);
updf(node[2 * nk + 1], lazy[nk], width[2 * nk + 1]);
if (lazyflag[2 * nk])lazyf(lazy[2 * nk], lazy[nk]);
else lazy[2 * nk] = lazy[nk];
if (lazyflag[2 * nk + 1])lazyf(lazy[2 * nk + 1], lazy[nk]);
else lazy[2 * nk + 1] = lazy[nk];
lazyflag[2 * nk] = lazyflag[2 * nk + 1] = true;
lazyflag[nk] = false;
}
}
}
public:
SegTree(unsigned int m, T init) {
while (n < m) {
n *= 2;
rank++;
}
node.resize(2 * n); lazy.resize(2 * n); lazyflag.resize(2 * n, false); width.resize(2 * n);
for (int i = n; i < 2 * n; i++)node[i] = init;
width[1] = n;
for (int i = 2; i < 2 * n; i++) {
width[i] = width[i >> 1] >> 1;
}
}
SegTree(const vector<T>& initvec) {
unsigned int m = initvec.size();
while (n < m) {
n *= 2;
rank++;
}
node.resize(2 * n); lazy.resize(2 * n); lazyflag.resize(2 * n, false); width.resize(2 * n);
for (int i = n; i < 2 * n; i++) {
if (i - n < m)node[i] = initvec[i - n];
}
width[1] = n;
for (int i = 2; i < 2 * n; i++) {
width[i] = width[i >> 1] >> 1;
}
}
virtual void update(int i, U x) {
i += n;
eval(i);
updf(node[i], x, width[i]);
if (lazyflag[i])lazyf(lazy[i], x);
else {
lazyflag[i] = true;
lazy[i] = x;
}
}
virtual void update(int l, int r, U x) {
l += n; r += n;
int nl = l, nr = r;
while (!(nl & 1))nl >>= 1;
while (!(nr & 1))nr >>= 1;
nr--;
eval(nl); eval(nr);
while (l < r) {
if (l & 1) {
updf(node[l], x, width[l]);
if (lazyflag[l])lazyf(lazy[l], x);
else {
lazyflag[l] = true;
lazy[l] = x;
}
l++;
}
if (r & 1) {
r--;
updf(node[r], x, width[r]);
if (lazyflag[r])lazyf(lazy[r], x);
else {
lazyflag[r] = true;
lazy[r] = x;
}
}
l >>= 1; r >>= 1;
}
}
T operator[](const int& x) {
eval(x + n);
return node[x + n];
}
void fill(T x) {
std::fill(all(lazyflag), false);
std::fill(all(node), x);
}
void print() {
rep(i, n)cout << operator[](i) << " ";
cout << endl;
}
};
class RAQ :public SegTree<lint, lint> {
void lazyf(lint& a, const lint& b) { a += b; }
void updf(lint& a, const lint& b, const unsigned int& width) { a += width * b; }
public:
RAQ(int size, const lint& def = 0) :SegTree<lint, lint>(size, def) {}
RAQ(const vector<lint>& initvec) :SegTree<lint, lint>(initvec) {}
};
class RUQ :public SegTree<lint, lint> {
void lazyf(lint& a, const lint& b) { a = b; }
void updf(lint& a, const lint& b, const unsigned int& width) { a = b; }
public:
RUQ(int size, const lint& def = 0) :SegTree<lint, lint>(size, def) {}
RUQ(const vector<lint>& initvec) :SegTree<lint, lint>(initvec) {}
};
template<typename T, typename U>
class IntervalSegTree :public SegTree<T, U> {
protected:
using SegTree<T, U>::n;
using SegTree<T, U>::rank;
using SegTree<T, U>::node;
using SegTree<T, U>::lazy;
using SegTree<T, U>::lazyflag;
using SegTree<T, U>::width;
using SegTree<T, U>::eval;
using SegTree<T, U>::lazyf;
using SegTree<T, U>::updf;
T nodee;
virtual T nodef(const T&, const T&)const = 0;
public:
IntervalSegTree(unsigned int m, T init, T nodee) :SegTree<T, U>(m, init), nodee(nodee) {}
IntervalSegTree(T nodee, const vector<T>& initvec) :SegTree<T, U>(initvec), nodee(nodee) {}
void update(int i, U x) {
i += n;
eval(i);
updf(node[i], x, width[i]);
if (lazyflag[i])lazyf(lazy[i], x);
else {
lazyflag[i] = true;
lazy[i] = x;
}
while (i /= 2)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
void update(int l, int r, U x) {
l += n; r += n;
int nl = l, nr = r;
while (!(nl & 1))nl >>= 1;
while (!(nr & 1))nr >>= 1;
nr--;
eval(nl); eval(nr);
while (l < r) {
if (l & 1) {
updf(node[l], x, width[l]);
if (lazyflag[l])lazyf(lazy[l], x);
else {
lazyflag[l] = true;
lazy[l] = x;
}
l++;
}
if (r & 1) {
r--;
updf(node[r], x, width[r]);
if (lazyflag[r])lazyf(lazy[r], x);
else {
lazyflag[r] = true;
lazy[r] = x;
}
}
l >>= 1; r >>= 1;
}
while (nl >>= 1)node[nl] = nodef(node[2 * nl], node[2 * nl + 1]);
while (nr >>= 1)node[nr] = nodef(node[2 * nr], node[2 * nr + 1]);
}
T query(int l, int r) {
l += n; r += n;
eval(l); eval(r - 1);
int ls = nodee, rs = nodee;
while (l < r) {
if (l & 1) {
ls = nodef(ls, node[l]);
l++;
}
if (r & 1) {
r--;
rs = nodef(node[r], rs);
}
l >>= 1; r >>= 1;
}
return nodef(ls, rs);
}
T queryForAll() {
return node[1];
}
void print() {
rep(i, n)cout << SegTree<T, U>::query(i) << " ";
cout << endl;
}
};
class RAQRSQ :public IntervalSegTree<lint, lint> {
lint nodef(const lint& a, const lint& b)const { return a + b; }
void lazyf(lint& a, const lint& b) { a += b; }
void updf(lint& a, const lint& b, const unsigned int& width) { a += width * b; }
public:
RAQRSQ(int size, const lint& def = 0) :IntervalSegTree<lint, lint>(size, def, 0) {
for (int i = n - 1; i > 0; i--)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
RAQRSQ(const vector<lint>& initvec) :IntervalSegTree<lint, lint>((lint)0, initvec) {
for (int i = n - 1; i > 0; i--)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
};
class RAQRMiQ :public IntervalSegTree<lint, lint> {
lint nodef(const lint& a, const lint& b)const { return min(a, b); }
void lazyf(lint& a, const lint& b) { a += b; }
void updf(lint& a, const lint& b, const unsigned int& width) { a += b; }
public:
RAQRMiQ(int size, const lint& def = 0) :IntervalSegTree<lint, lint>(size, def, LINF) {
for (int i = n - 1; i > 0; i--)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
RAQRMiQ(const vector<lint>& initvec) :IntervalSegTree<lint, lint>(LINF, initvec) {
for (int i = n - 1; i > 0; i--)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
};
class RAQRMaQ :public IntervalSegTree<lint, lint> {
lint nodef(const lint& a, const lint& b)const { return max(a, b); }
void lazyf(lint& a, const lint& b) { a += b; }
void updf(lint& a, const lint& b, const unsigned int& width) { a += b; }
public:
RAQRMaQ(unsigned int size, const lint& def = 0) :IntervalSegTree<lint, lint>(size, def, -LINF) {
for (int i = n - 1; i > 0; i--)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
RAQRMaQ(const vector<lint>& initvec) :IntervalSegTree<lint, lint>(-LINF, initvec) {
for (int i = n - 1; i > 0; i--)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
};
class RUQRSQ :public IntervalSegTree<lint, lint> {
lint nodef(const lint& a, const lint& b)const { return a + b; }
void lazyf(lint& a, const lint& b) { a = b; }
void updf(lint& a, const lint& b, const unsigned int& width) { a = width * b; }
public:
RUQRSQ(int size, const int& def = 0) :IntervalSegTree<lint, lint>(size, def, 0) {
for (int i = n - 1; i > 0; i--)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
RUQRSQ(const vector<lint>& initvec) :IntervalSegTree<lint, lint>((lint)0, initvec) {
for (int i = n - 1; i > 0; i--)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
};
class RUQRMiQ :public IntervalSegTree<lint, lint> {
lint nodef(const int& a, const int& b)const { return min(a, b); }
void lazyf(int& a, const int& b) { a = b; }
void updf(int& a, const int& b, const unsigned int& width) { a = b; }
public:
RUQRMiQ(int size, const lint& def = 0) :IntervalSegTree<lint, lint>(size, def, LINF) {
for (int i = n - 1; i > 0; i--)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
RUQRMiQ(const vector<lint>& initvec) :IntervalSegTree<lint, lint>(LINF, initvec) {
for (int i = n - 1; i > 0; i--)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
};
class RUQRMaQ :public IntervalSegTree<lint, lint> {
lint nodef(const lint& a, const lint& b)const { return max(a, b); }
void lazyf(lint& a, const lint& b) { a = b; }
void updf(lint& a, const lint& b, const unsigned int& width) { a = b; }
public:
RUQRMaQ(int size, const lint& def = 0) :IntervalSegTree<lint, lint>(size, def, -LINF) {
for (int i = n - 1; i > 0; i--)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
RUQRMaQ(const vector<lint>& initvec) :IntervalSegTree<lint, lint>(-LINF, initvec) {
for (int i = n - 1; i > 0; i--)node[i] = nodef(node[2 * i], node[2 * i + 1]);
}
};
int n, a[1010][1010], b[2][1010];
Vector<P> home[1010];
int main() {
std::cin >> n;
rep(i, n) {
rep(j, n) {
std::cin >> a[i][j];
home[a[i][j]].emplace_back(i, j);
}
}
lint ans = 0;
RAQRSQ st1(n), st2(n);
REP(i, n) {
st1.fill(0); st2.fill(0);
for (P j : home[i]) {
if (j.first + j.second + 1 < n)st1.update(j.first + j.second + 1, n, 1);
if (0 <= j.first - j.second - 1)st2.update(0, j.first - j.second, 1);
ans += j.second;
}
rep(j, n - 1)st1.update(j + 1, j + 2, st1[j]);
for (int j = n - 1; j > 0; j--)st2.update(j - 1, j, st2[j]);
int cnt = INF;
rep(j, n)chmin(cnt, st1[j] + st2[j]);
ans += cnt;
}
std::cout << ans << std::endl;
return 0;
}
kaage