結果
問題 | No.1115 二つの数列 / Two Sequences |
ユーザー | ningenMe |
提出日時 | 2021-04-23 16:27:27 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 642 ms / 2,000 ms |
コード長 | 11,401 bytes |
コンパイル時間 | 3,238 ms |
コンパイル使用メモリ | 244,580 KB |
実行使用メモリ | 256,664 KB |
最終ジャッジ日時 | 2024-07-04 07:09:15 |
合計ジャッジ時間 | 13,279 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 15 ms
9,984 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 459 ms
204,520 KB |
testcase_04 | AC | 558 ms
252,020 KB |
testcase_05 | AC | 452 ms
202,712 KB |
testcase_06 | AC | 398 ms
178,884 KB |
testcase_07 | AC | 553 ms
249,416 KB |
testcase_08 | AC | 8 ms
6,656 KB |
testcase_09 | AC | 141 ms
113,932 KB |
testcase_10 | AC | 318 ms
256,664 KB |
testcase_11 | AC | 2 ms
5,376 KB |
testcase_12 | AC | 623 ms
256,660 KB |
testcase_13 | AC | 642 ms
256,660 KB |
testcase_14 | AC | 573 ms
256,664 KB |
testcase_15 | AC | 2 ms
5,376 KB |
testcase_16 | AC | 1 ms
5,376 KB |
testcase_17 | AC | 2 ms
5,376 KB |
testcase_18 | AC | 1 ms
5,376 KB |
testcase_19 | AC | 2 ms
5,376 KB |
testcase_20 | AC | 2 ms
5,376 KB |
testcase_21 | AC | 1 ms
5,376 KB |
testcase_22 | AC | 2 ms
5,376 KB |
testcase_23 | AC | 14 ms
9,984 KB |
testcase_24 | AC | 121 ms
57,396 KB |
testcase_25 | AC | 374 ms
165,928 KB |
testcase_26 | AC | 42 ms
22,612 KB |
testcase_27 | AC | 167 ms
77,664 KB |
testcase_28 | AC | 271 ms
121,212 KB |
testcase_29 | AC | 400 ms
181,068 KB |
testcase_30 | AC | 539 ms
236,880 KB |
testcase_31 | AC | 63 ms
34,308 KB |
testcase_32 | AC | 34 ms
20,156 KB |
testcase_33 | AC | 253 ms
208,528 KB |
testcase_34 | AC | 2 ms
5,376 KB |
testcase_35 | AC | 2 ms
5,376 KB |
testcase_36 | AC | 2 ms
5,376 KB |
testcase_37 | AC | 2 ms
5,376 KB |
testcase_38 | AC | 2 ms
5,376 KB |
testcase_39 | AC | 1 ms
5,376 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; using int128 = __int128_t; using int64 = long long; using int32 = int; using uint128 = __uint128_t; using uint64 = unsigned long long; using uint32 = unsigned int; #define ALL(obj) (obj).begin(),(obj).end() template<class T> using priority_queue_reverse = priority_queue<T,vector<T>,greater<T>>; constexpr int64 MOD = 1'000'000'000LL + 7; //' constexpr int64 MOD2 = 998244353; constexpr int64 HIGHINF = 1'000'000'000'000'000'000LL; constexpr int64 LOWINF = 1'000'000'000'000'000LL; //' constexpr long double PI = 3.1415926535897932384626433L; template <class T> vector<T> multivector(size_t N,T init){return vector<T>(N,init);} template <class... T> auto multivector(size_t N,T... t){return vector<decltype(multivector(t...))>(N,multivector(t...));} template <class T> void corner(bool flg, T hoge) {if (flg) {cout << hoge << endl; exit(0);}} template <class T, class U>ostream &operator<<(ostream &o, const map<T, U>&obj) {o << "{"; for (auto &x : obj) o << " {" << x.first << " : " << x.second << "}" << ","; o << " }"; return o;} template <class T>ostream &operator<<(ostream &o, const set<T>&obj) {o << "{"; for (auto itr = obj.begin(); itr != obj.end(); ++itr) o << (itr != obj.begin() ? ", " : "") << *itr; o << "}"; return o;} template <class T>ostream &operator<<(ostream &o, const multiset<T>&obj) {o << "{"; for (auto itr = obj.begin(); itr != obj.end(); ++itr) o << (itr != obj.begin() ? ", " : "") << *itr; o << "}"; return o;} template <class T>ostream &operator<<(ostream &o, const vector<T>&obj) {o << "{"; for (int i = 0; i < (int)obj.size(); ++i)o << (i > 0 ? ", " : "") << obj[i]; o << "}"; return o;} template <class T>ostream &operator<<(ostream &o, const deque<T>&obj) {o << "{"; for (int i = 0; i < (int)obj.size(); ++i)o << (i > 0 ? ", " : "") << obj[i]; o << "}"; return o;} template <class T, class U>ostream &operator<<(ostream &o, const pair<T, U>&obj) {o << "{" << obj.first << ", " << obj.second << "}"; return o;} void print(void) {cout << endl;} template <class Head> void print(Head&& head) {cout << head;print();} template <class Head, class... Tail> void print(Head&& head, Tail&&... tail) {cout << head << " ";print(forward<Tail>(tail)...);} template <class T> void chmax(T& a, const T b){a=max(a,b);} template <class T> void chmin(T& a, const T b){a=min(a,b);} vector<string> split(const string &str, const char delemiter) {vector<string> res;stringstream ss(str);string buffer; while( getline(ss, buffer, delemiter) ) res.push_back(buffer); return res;} inline constexpr int msb(int x) {return x?31-__builtin_clz(x):-1;} inline constexpr int64 ceil_div(const int64 a,const int64 b) {return (a+(b-1))/b;}// return ceil(a/b) void YN(bool flg) {cout << (flg ? "YES" : "NO") << endl;} void Yn(bool flg) {cout << (flg ? "Yes" : "No") << endl;} void yn(bool flg) {cout << (flg ? "yes" : "no") << endl;} /* * @title BinaryIndexedTree * @docs md/segment/BinaryIndexedTree.md */ template<class Operator> class BinaryIndexedTree { using TypeNode = typename Operator::TypeNode; size_t depth; size_t length; size_t num; vector<TypeNode> node; public: //[0,N) constructed, inplace [0,1) + [1,N+1) //you can ignore inplace offset BinaryIndexedTree(const size_t num) : num(num) { for (depth = 1,length = 1; length < num; depth++,length *= 2); node.resize(length+1, Operator::unit_node); } //[idx,idx+1) update void update(size_t idx, TypeNode var) { assert(0 <= idx && idx < length); for (++idx; idx <= length; idx += idx & -idx) node[idx] = Operator::func_node(node[idx],var); } //[0,idx) get TypeNode get(size_t idx) { TypeNode ret = Operator::unit_node; for (idx = min(length,idx); idx > 0; idx -= idx & -idx) ret = Operator::func_node(ret,node[idx]); return ret; } //return [0,length] int binary_search(TypeNode var) { if(!Operator::func_check(node.back(),var)) return num; TypeNode ret = Operator::unit_node; size_t off = 0; for(size_t idx = length; idx; idx >>= 1){ if(off + idx <= length && !Operator::func_check(Operator::func_node(ret,node[off+idx]),var)) { off += idx; ret = Operator::func_node(ret,node[off]); } } return min(off,num); } void print() { cout << "{ " << get(1); for(int i = 1; i < length; ++i) cout << ", " << get(i+1); cout << " }" << endl; } }; template<class T> struct NodePrefixSumPointAdd { using TypeNode = T; inline static constexpr TypeNode unit_node = 0; inline static constexpr TypeNode func_node(const TypeNode& l,const TypeNode& r){return l+r;} // Binary Search for first index where func_check is true inline static constexpr bool func_check(const TypeNode nodeVal,const TypeNode& val){return val <= nodeVal;} }; /* * @title RangeInversionQuery - 区間転倒数 * @docs md/segment/RangeModeQuery.md */ template<class T> class RangeInversionQuery { vector<size_t> compressed; vector<long long> prefix_inv; vector<long long> suffix_inv; vector<vector<size_t>> sqrt_bucket_freq; vector<vector<long long>> sqrt_bucket_inv; vector<vector<size_t>> sqrt_bucket_sort_index; vector<size_t> sqrt_bucket_size; size_t N,B; public: RangeInversionQuery(const vector<T>& ar, T pre=-1) : compressed(ar.size()),prefix_inv(ar.size()),suffix_inv(ar.size()) { N = ar.size(); B = sqrt(N) + 1; //zarts { vector<pair<T,size_t>> ord(N); for(size_t i=0;i<N;++i) ord[i]={ar[i],i}; sort(ord.begin(),ord.end()); size_t inc=0; for(size_t i=0;i<N;++i) { if(pre < ord[i].first) inc++; compressed[ord[i].second] = inc; pre = ord[i].first; } } //freq { sqrt_bucket_freq.resize(B); vector<size_t> freq(N+1,0); for(size_t i=0;i<B;++i) { size_t l = i*B, r = min((i+1)*B,N); for(size_t j=l;j<r;++j) freq[compressed[j]]++; sqrt_bucket_freq[i] = freq; for(size_t j=1;j<=N;++j) sqrt_bucket_freq[i][j]+=sqrt_bucket_freq[i][j-1]; } } //prefix,suffix inv { BinaryIndexedTree<NodePrefixSumPointAdd<long long>> bit(N+1); for(size_t i=0;i<B;++i) { int l = i*B, r = min((i+1)*B,N); //prefix { long long inv = 0; for(size_t j=l;j<r;++j) { inv += bit.get(N+1)-bit.get(compressed[j]+1); prefix_inv[j]=inv; bit.update(compressed[j],1); } for(size_t j=l;j<r;++j) { bit.update(compressed[j],-1); } } //suffix { long long inv = 0; for(int j=r-1;l<=j;--j) { inv += bit.get(compressed[j]); suffix_inv[j]=inv; bit.update(compressed[j],1); } for(size_t j=l;j<r;++j) { bit.update(compressed[j],-1); } } } } //sqrt bucket inv { sqrt_bucket_inv.resize(B,vector<long long>(B,0)); for(size_t i=0;i<B;++i) { size_t l = i*B, r = min((i+1)*B,N); if(l<r) sqrt_bucket_inv[i][i] = prefix_inv[r-1]; } for(size_t k=1;k<B;++k) { for(size_t i=0;i+k<B;++i) { sqrt_bucket_inv[i][i+k] += sqrt_bucket_inv[i][i]+sqrt_bucket_inv[i+1][i+k]; size_t l = i*B, r = min((i+1)*B,N); for(size_t j=l;j<r;++j) { size_t& c = compressed[j]; sqrt_bucket_inv[i][i+k] += (sqrt_bucket_freq[i+k][c-1]-sqrt_bucket_freq[i][c-1]); } } } } //sort { sqrt_bucket_sort_index.resize(B); sqrt_bucket_size.resize(B,0); size_t sz = 0; for(size_t i=0;i<B;++i) { int l = i*B, r = min((i+1)*B,N); sz += max(0,(r-l)); sqrt_bucket_size[i] = sz; if(r-l<1) continue; sqrt_bucket_sort_index[i].resize(r-l); for(size_t j=l;j<r;++j) sqrt_bucket_sort_index[i][j-l]=j; sort(sqrt_bucket_sort_index[i].begin(),sqrt_bucket_sort_index[i].end(), [&](size_t l,size_t r){return compressed[l]==compressed[r]?l<r:compressed[l]<compressed[r];}); } } } //query [l,r) //return {freq,mode} ({頻度,元の配列における値}) long long get(int l, int r) { int bl = l/B + 1, br = (r-1)/B - 1; long long inv = 0; //同じbucketにl,rがあるとき if(bl > br + 1) { inv += prefix_inv[r-1]; if(l) inv -= prefix_inv[l-1]; bl = l / B; long long sum = 0; for(size_t i: sqrt_bucket_sort_index[bl]) { if(r <= i) continue; if(l <= i) sum++; else inv -= sum; } } else { if(bl<=br) inv += sqrt_bucket_inv[bl][br]; inv += suffix_inv[l]; inv += prefix_inv[r-1]; size_t ml = bl*B; for(size_t i=l;i<ml;++i) { size_t& c = compressed[i]; inv += sqrt_bucket_freq[br][c-1]-sqrt_bucket_freq[bl-1][c-1]; } size_t mr = (br+1)*B; for(size_t i=mr;i<r;++i) { size_t& c = compressed[i]; inv += (sqrt_bucket_size[br]-sqrt_bucket_freq[br][c])-(sqrt_bucket_size[bl-1]-sqrt_bucket_freq[bl-1][c]); } queue<size_t> ql,qr; for(size_t i: sqrt_bucket_sort_index[bl-1]) ql.push(i); for(size_t i: sqrt_bucket_sort_index[br+1]) qr.push(i); long long sum = 0; while(ql.size()) { auto xl = ql.front(); if(xl < l) { ql.pop(); continue; } if(qr.empty()) { inv += sum; ql.pop(); continue; } auto xr = qr.front(); if(xr >= r) { qr.pop(); continue; } if(compressed[xl] > compressed[xr]) { sum++; qr.pop(); continue; } else { inv += sum; ql.pop(); continue; } } } return inv; } }; /** * @url * @est */ int main() { int N; cin >> N; vector<int> a(N),b(N),c(N+1); for(int i = 0; i < N; ++i) { cin >> a[i]; c[a[i]]=i; } for(int i = 0; i < N; ++i) { cin >> b[i]; b[i]=c[b[i]]; } vector<int> idx(N); iota(ALL(idx),0); sort(ALL(idx),[&](int l,int r){return b[l]<b[r];}); RangeInversionQuery<int> riq(idx); cout << riq.get(0,N) << endl; return 0; }