Created
April 16, 2021 08:10
-
-
Save aryan57/bfcba8b82f54402307de8c2f00839bc4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
author : Aryan Agarwal, IIT Kharagpur | |
created : 03-April-2021 18:05:23 IST | |
*/ | |
#include <bits/stdc++.h> | |
using namespace std; | |
void __print(int x) {cerr << x;} | |
void __print(long x) {cerr << x;} | |
void __print(long long x) {cerr << x;} | |
void __print(unsigned x) {cerr << x;} | |
void __print(unsigned long x) {cerr << x;} | |
void __print(unsigned long long x) {cerr << x;} | |
void __print(float x) {cerr << x;} | |
void __print(double x) {cerr << x;} | |
void __print(long double x) {cerr << x;} | |
void __print(char x) {cerr << '\'' << x << '\'';} | |
void __print(const char *x) {cerr << '\"' << x << '\"';} | |
void __print(const string &x) {cerr << '\"' << x << '\"';} | |
void __print(bool x) {cerr << (x ? "true" : "false");} | |
template<typename T, typename V> | |
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';} | |
template<typename T> | |
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";} | |
void _print() {cerr << "]\n";} | |
template <typename T, typename... V> | |
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);} | |
#ifndef ONLINE_JUDGE | |
#define dbg(x...) cerr << "[" << #x << "] = ["; _print(x) | |
#else | |
#define dbg(x...) | |
#endif | |
#define int long long | |
#define X first | |
#define Y second | |
#define pb push_back | |
#define sz(a) ((int)(a).size()) | |
#define all(a) (a).begin(), (a).end() | |
#define F(i, a, b) for (int i = a; i <= b; i++) | |
#define RF(i, a, b) for (int i = a; i >= b; i--) | |
const int mxn = 1e5; | |
const long long INF = 2e18; | |
const int32_t M = 1000000007; | |
// const int32_t M = 998244353; | |
const long double pie = acos(-1); | |
/* | |
It is the data structure for monoids i.e., the algebraic structure that satisfies the following properties : | |
associativity: (a⋅b)⋅c = a⋅(b⋅c) for all a,b,c ∈ S | |
existence of the identity element: a⋅e = e⋅a = a for all a ∈ S | |
(1) segtree<S, binary_operation, identity_element> seg(int n) | |
(2) segtree<S, binary_operation, identity_element> seg(vector<S> v) | |
(1): It creates an array a of length n. All the elements are initialized to identity_element(). | |
(2): It creates an array a of length n = v.size(), initialized to v. | |
0≤n≤10**8 | |
O(n) | |
void seg.set(int p, S x) | |
It assigns x to a[p] | |
0≤p<n | |
O(logn) | |
S seg.get(int p) | |
It returns a[p] | |
0≤p<n | |
O(1) | |
S seg.prod(int l, int r) | |
It returns binary_operation(a[l], ..., a[r - 1]), assuming the properties of the monoid. It returns identity_element() if l=r. | |
0≤l≤r≤n | |
O(logn) | |
S seg.all_prod() | |
It returns op(a[0], ..., a[n - 1]), assuming the properties of the monoid. It returns identity_element() if n=0. | |
O(1) | |
(1) int seg.max_right<check_function>(int l) | |
(2) int seg.max_right<F>(int l, F check_function) | |
(1): It applies binary search on the segment tree. The function bool check_function(S x) should be defined. | |
(2): The function object that takes S as the argument and returns bool should be defined. | |
It returns an index r that satisfies both of the following :- | |
r = l or check_function(binary_operation(a[l], a[l + 1], ..., a[r - 1])) = true | |
r = n or check_function(binary_operation(a[l], a[l + 1], ..., a[r])) = false | |
If check_function is monotone, this is the maximum r that satisfies check_function(binary_operation(a[l], a[l+1], ..,a[r-1]))=true | |
if check_function is called with the same argument, it returns the same value, i.e., check_function has no side effect. | |
check_function(identity_element()) = true | |
0≤l≤n | |
O(logn) | |
(1) int seg.min_left<check_function>(int r) | |
(2) int seg.min_left<F>(int r, F check_function) | |
(1): It applies binary search on the segment tree. The function bool check_function(S x) should be defined. | |
(2): The function object that takes S as the argument and returns bool should be defined. | |
It returns an index l that satisfies both of the following :- | |
l = r or check_function(binary_operation(a[l], a[l + 1], ..., a[r - 1])) = true | |
l = 0 or check_function(binary_operation(a[l - 1], a[l], ..., a[r - 1])) = false | |
If check_function is monotone, this is the minimum l that satisfies check_function(binary_operation(a[l], a[l+1], ..,a[r-1]))=true | |
if check_function is called with the same argument, it returns the same value, i.e., check_function has no side effect. | |
check_function(identity_element()) = true | |
0≤r≤n | |
O(logn) | |
https://atcoder.github.io/ac-library/production/document_en/segtree.html | |
*/ | |
template <class S, S (*op)(S, S), S (*e)()> struct segtree { | |
public: | |
segtree() : segtree(0) {} | |
explicit segtree(int n) : segtree(std::vector<S>(n, e())) {} | |
explicit segtree(const std::vector<S>& v) : _n((int)(v.size())) { | |
log = segtree::ceil_pow2(_n); | |
size = 1 << log; | |
d = std::vector<S>(2 * size, e()); | |
for (int i = 0; i < _n; i++) d[size + i] = v[i]; | |
for (int i = size - 1; i >= 1; i--) { | |
update(i); | |
} | |
} | |
void set(int p, S x) { | |
assert(0 <= p && p < _n); | |
p += size; | |
d[p] = x; | |
for (int i = 1; i <= log; i++) update(p >> i); | |
} | |
S get(int p) const { | |
assert(0 <= p && p < _n); | |
return d[p + size]; | |
} | |
S prod(int l, int r) const { | |
assert(0 <= l && l <= r && r <= _n); | |
S sml = e(), smr = e(); | |
l += size; | |
r += size; | |
while (l < r) { | |
if (l & 1) sml = op(sml, d[l++]); | |
if (r & 1) smr = op(d[--r], smr); | |
l >>= 1; | |
r >>= 1; | |
} | |
return op(sml, smr); | |
} | |
S all_prod() const { return d[1]; } | |
template <bool (*f)(S)> int max_right(int l) const { | |
return max_right(l, [](S x) { return f(x); }); | |
} | |
template <class F> int max_right(int l, F f) const { | |
assert(0 <= l && l <= _n); | |
assert(f(e())); | |
if (l == _n) return _n; | |
l += size; | |
S sm = e(); | |
do { | |
while (l % 2 == 0) l >>= 1; | |
if (!f(op(sm, d[l]))) { | |
while (l < size) { | |
l = (2 * l); | |
if (f(op(sm, d[l]))) { | |
sm = op(sm, d[l]); | |
l++; | |
} | |
} | |
return l - size; | |
} | |
sm = op(sm, d[l]); | |
l++; | |
} while ((l & -l) != l); | |
return _n; | |
} | |
template <bool (*f)(S)> int min_left(int r) const { | |
return min_left(r, [](S x) { return f(x); }); | |
} | |
template <class F> int min_left(int r, F f) const { | |
assert(0 <= r && r <= _n); | |
assert(f(e())); | |
if (r == 0) return 0; | |
r += size; | |
S sm = e(); | |
do { | |
r--; | |
while (r > 1 && (r % 2)) r >>= 1; | |
if (!f(op(d[r], sm))) { | |
while (r < size) { | |
r = (2 * r + 1); | |
if (f(op(d[r], sm))) { | |
sm = op(d[r], sm); | |
r--; | |
} | |
} | |
return r + 1 - size; | |
} | |
sm = op(d[r], sm); | |
} while ((r & -r) != r); | |
return 0; | |
} | |
private: | |
int _n, size, log; | |
std::vector<S> d; | |
void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } | |
// @param n `0 <= n` | |
// @return minimum non-negative `x` s.t. `n <= 2**x` | |
int ceil_pow2(int n) { | |
int x = 0; | |
while ((1U << x) < (unsigned int)(n)) x++; | |
return x; | |
} | |
}; | |
int binary_operation(int a,int b) | |
{ | |
return a+b; | |
} | |
int identity_element() | |
{ | |
return 0; | |
} | |
int target; | |
bool check_function(int v) | |
{ | |
return v<target; | |
} | |
void solve_LOG() | |
{ | |
int n; | |
cin>>n; | |
segtree <int,binary_operation,identity_element> tree(n); | |
F(i,0,n-1) | |
{ | |
int x; | |
cin>>x; | |
x--; | |
cout<<tree.prod(x,n)<<" "; | |
tree.set(x,1); | |
} | |
} | |
signed main() | |
{ | |
ios_base::sync_with_stdio(false); | |
cin.tie(nullptr); | |
cout.tie(nullptr); | |
#ifndef ONLINE_JUDGE | |
// freopen("input.txt","r",stdin); | |
// freopen("output.txt","w",stdout); | |
#endif | |
#ifdef ARYAN_SIEVE | |
// defualt mxn_sieve = 1e5 | |
sieve(); | |
#endif | |
#ifdef ARYAN_SEG_SIEVE | |
// default [L,R] = [1,1e5] | |
segmented_sieve(); | |
#endif | |
#ifdef ARYAN_FACT | |
// default mxn_fact = 1e5 | |
fact_init(); | |
#endif | |
// cout<<fixed<<setprecision(10); | |
int _t=1; | |
// cin>>_t; | |
for (int i=1;i<=_t;i++) | |
{ | |
// cout<<"Case #"<<i<<": "; | |
solve_LOG(); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment