結果
問題 | No.1804 Intersection of LIS |
ユーザー |
![]() |
提出日時 | 2022-01-08 18:29:54 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 435 ms / 2,000 ms |
コード長 | 4,230 bytes |
コンパイル時間 | 2,239 ms |
コンパイル使用メモリ | 183,488 KB |
実行使用メモリ | 25,408 KB |
最終ジャッジ日時 | 2024-11-14 09:42:46 |
合計ジャッジ時間 | 11,518 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 37 |
ソースコード
/*** @FileName a.cpp* @Author kanpurin* @Created 2022.01.08 18:29:52**/#include "bits/stdc++.h"using namespace std;typedef long long ll;template < class Monoid >struct SegmentTree {private:using Func = std::function< Monoid(Monoid, Monoid) >;Func F;Monoid UNITY;int n;std::vector< Monoid > node;int _binary_search(int a, int b, const std::function<bool(Monoid)> &f, Monoid &s, int k = 0, int l = 0, int r = -1) {if (r < 0) r = n;if (r <= a || b <= l) return n;if (a <= l && r <= b && !f(F(s,node[k]))) {s = F(s,node[k]);return n;}if (l == r - 1) {s = F(s,node[k]); return l;}int ret = _binary_search(a, b, f, s, 2 * k + 1, l, (r - l) / 2 + l);return ret != n ? ret : _binary_search(a, b, f, s, 2 * k + 2, (r - l) / 2 + l, r);}public:SegmentTree() {}SegmentTree(const std::vector< Monoid > &v, const Func f, const Monoid &unity) {F = f;UNITY = unity;int sz = v.size();n = 1;while (n < sz) n <<= 1;node.resize(n * 2 - 1, UNITY);for (int i = 0; i < sz; i++) node[i + n - 1] = v[i];build();}SegmentTree(int m, const Monoid &val, const Func f, const Monoid &unity) {F = f;UNITY = unity;n = 1;while (n < m) n <<= 1;node.resize(n * 2 - 1, UNITY);if (val != UNITY) {for (int i = 0; i < m; i++) node[i + n - 1] = val;build();}}void set(int k, const Monoid &x) {node[n + k - 1] = x;}void build() {for (int i = n - 2; i >= 0; i--) node[i] = F(node[2 * i + 1], node[2 * i + 2]);}void update_query(int x, const Monoid &val) {if (x >= n || x < 0) return;x += n - 1;node[x] = val;while (x > 0) {x = (x - 1) >> 1;node[x] = F(node[2 * x + 1], node[2 * x + 2]);}}Monoid get_query(int l, int r) {Monoid L = UNITY, R = UNITY;if (l < 0) l = 0;if (r < 0) return UNITY;if (l >= n) return UNITY;if (r >= n) r = n;for (l += n, r += n; l < r; l >>= 1, r >>= 1) {if (l & 1) L = F(L, node[l++ - 1]);if (r & 1) R = F(node[--r - 1], R);}return F(L, R);}int binary_search(int l, int r, const std::function<bool(Monoid)> &f) {Monoid s = UNITY;int ret = _binary_search(l,r,f,s);return ret != n ? ret : -1;}Monoid operator[](int x) const {return node[n + x - 1];}int size() {return n;}void print() {for (int i = 0; i < n; i++) {std::cout << i << "\t: " << node[n + i - 1] << std::endl;}}};int main() {int n;cin >> n;vector<int> p(n);for (int i = 0; i < n; i++) {cin >> p[i];p[i]--;}vector<int> idx(n);iota(idx.begin(), idx.end(),0);sort(idx.begin(), idx.end(),[&](int a,int b){return p[a] < p[b];});SegmentTree<int> seg1(n,0,[](int a,int b){return max(a,b);},0);SegmentTree<int> seg2(n,0,[](int a,int b){return max(a,b);},0);vector<int> val(n,-1);for (int i = 0; i < n; i++) {int v = seg1.get_query(0,idx[i])+1;val[i] += v;seg1.update_query(idx[i],v);}for (int i = n-1; i >= 0; i--) {int v = seg2.get_query(idx[i]+1,n)+1;val[i] += v;seg2.update_query(idx[i],v);}SegmentTree<int> seg3(n,0,[](int a,int b){return max(a,b);},0);SegmentTree<int> seg4(n,0,[](int a,int b){return max(a,b);},0);vector<bool> isOK(n,true);vector<int> ans;for (int i = 0; i < n; i++) {if (val[i] <= seg3.get_query(idx[i]+1,n)) isOK[i] = false;seg3.update_query(idx[i],val[i]);}for (int i = n-1; i >= 0; i--) {if (val[i] <= seg4.get_query(0,idx[i])) isOK[i] = false;seg4.update_query(idx[i],val[i]);}for (int i = 0; i < n; i++) {if (isOK[i]) ans.push_back(i+1);}cout << ans.size() << endl;for (int &a : ans) cout << a << " ";cout << endl;return 0;}