CSES - Shared codeLink to this code:
https://cses.fi/paste/ab15a9545c0ffe8e2825be/
#include <bits/stdc++.h>
using namespace std;
#define ms(s,n) memset(s,n,sizeof(s))
#define all(a) a.begin(),a.end()
#define present(t, x) (t.find(x) != t.end())
#define sz(a) int((a).size())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define FORd(i, a, b) for (int i = (a) - 1; i >= (b); --i)
#define pb push_back
#define pf push_front
#define fi first
#define se second
#define mp make_pair
#define endl "\n"
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int,int> pi;
typedef vector<int> vi;
typedef vector<pi> vii;
const int MOD = (int) 1e9+7;
const int INF = (int) 1e9+1;
inline ll gcd(ll a,ll b){ll r;while(b){r=a%b;a=b;b=r;}return a;}
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
bool cmp(pair<pi,int> a, pair<pi,int> b){
if(a.fi.fi != b.fi.fi)
return a.fi.fi < b.fi.fi;
return a.fi.se > b.fi.se;
}
vector<int> BIT(200001);
void update(int n, int idx, int value){
while(idx <= n){
BIT[idx] += value;
idx += idx & -idx;
}
}
int query(int idx){
int sum = 0;
while(idx > 0){
sum += BIT[idx];
idx -= idx & -idx;
}
return sum;
}
int sum(int l, int r){
return query(r) - query(l - 1);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
pair<pi,int> a[n];
set<int> se;
map<int,int> mp;
for(int i = 0; i < n; i++){
cin >> a[i].fi.fi >> a[i].fi.se;
a[i].se = i;
se.insert(a[i].fi.se);
}
//dùng map để lưu chỉ số các điểm kết thúc của tất cả các đoạn
int cnt = 0;
for(int x : se){
mp[x] = ++cnt;
}
int chua[n]={0}, bichua[n]={0};
//Sắp xếp các đoạn theo thứ tự x tăng dần, nếu 2 đoạn có cùng x
//thì sắp xếp y giảm dần
sort(a, a + n, cmp);
BIT.assign(n+1, 0);
//Đoạn cuối cùng sẽ không chứa đoạn nào khác nên ko cần xét
update(cnt, mp[a[n - 1].fi.se], 1);
for(int i = n - 2; i >= 0; i--){
//Tổng số đoạn mà đoạn hiện tại chứa sẽ bằng tổng
//số lượng đoạn con có y <= y của đoạn hiện tại (a[i].fi.se)
//giá trị này có được bằng thao tác query, ta không cần xét điểm bắt đầu x
//của mỗi đoạn nữa vì nó đã sắp tăng dần rồi.
chua[a[i].se] = query(mp[a[i].fi.se]);
update(cnt, mp[a[i].fi.se], 1);
}
BIT.assign(n+1, 0);
//Đoạn đầu tiên sẽ không thể bị chứa
update(cnt, mp[a[0].fi.se], 1);
for(int i = 1; i < n; i++){
//Số lượng đoạn mà chứa đoạn hiện tại sẽ bằng tổng số
//đoạn có con kết thúc là y >= kết thúc của đoạn hiện tại
bichua[a[i].se] = sum(mp[a[i].fi.se], cnt);
update(cnt, mp[a[i].fi.se], 1);
}
for(int x : chua){
cout << x << " ";
}
cout << endl;
for(int x : bichua){
cout << x << " ";
}
}