This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
// Tanawin Thongbai
#include <bits/extc++.h>
using namespace std;
class Segm_Elem {
public:
bool is_real;
short st, ed;
int sum, unreal;
Segm_Elem() {
is_real = false;
st = 0;
ed = 0;
sum = 0;
unreal = 0;
}
Segm_Elem(int sum, int unreal, bool is_real, short st, short ed) {
this -> is_real = is_real;
this -> st = st;
this -> ed = ed;
this -> sum = sum;
this -> unreal = unreal;
}
};
const int N = 5000;
int orig[N + 1], indices[N + 1], less_before[N + 1][N + 1], cnts[N + 1][N + 2], dp_L[N + 1][N + 1], dp[N + 1];
Segm_Elem segm_merge(const Segm_Elem &a, const Segm_Elem &b) {
if(a.st == 0 && a.ed == 0) {
return b;
}
if(b.st == 0 && b.ed == 0) {
return a;
}
if(!a.is_real) {
if(b.is_real) {
return Segm_Elem(b.sum, a.unreal + a.ed - b.st, true, a.st, b.ed);
}
return Segm_Elem(0, a.unreal + b.unreal + a.ed - b.st, false, a.st, b.ed);
}
return Segm_Elem(a.sum + b.sum + b.unreal + a.ed - b.st, a.unreal, true, a.st, b.ed);
}
void segm_update(Segm_Elem *const &segm, const int &clogn, int index, Segm_Elem tr) {
index += (1 << clogn);
segm[index] = tr;
for(int i = index / 2; i >= 1; i /= 2) {
segm[i] = segm_merge(segm[i * 2], segm[i * 2 + 1]);
}
}
Segm_Elem segm_query(Segm_Elem *const &segm, const int &clogn, int st, int ed) {
int l = st + (1 << clogn);
int r = ed + (1 << clogn);
queue<Segm_Elem> l_part = queue<Segm_Elem>();
stack<Segm_Elem> r_part = stack<Segm_Elem>();
while(l <= r) {
if(l % 2 == 1) {
l_part.push(segm[l++]);
}
if(r % 2 == 0) {
r_part.push(segm[r--]);
}
l /= 2;
r /= 2;
}
bool first_time = true;
Segm_Elem ans;
while(!l_part.empty()) {
Segm_Elem s = l_part.front();
l_part.pop();
if(first_time) {
first_time = false;
ans = s;
} else {
ans = segm_merge(ans, s);
}
}
while(!r_part.empty()) {
Segm_Elem s = r_part.top();
r_part.pop();
if(first_time) {
first_time = false;
ans = s;
} else {
ans = segm_merge(ans, s);
}
}
return ans;
}
int main() {
int n_elem;
scanf("%d", &n_elem);
for(int i = 1; i <= n_elem; ++i) {
scanf("%d", &orig[i]);
indices[orig[i]] = i;
}
for(int i = 1; i <= n_elem; ++i) {
int cnt = 1;
for(int j = 1; j <= n_elem; ++j) {
if(i >= orig[j]) {
cnts[i][j] = cnt++;
}
}
int cnt_less = 0;
for(int j = 1; j <= n_elem; ++j) {
if(orig[j] < i) {
++cnt_less;
}
less_before[i][j] = cnt_less;
}
}
for(int i = 1; i <= n_elem - 1; ++i) {
dp_L[i][i] = 0;
int k = 1e9;
for(int j = i + 1; j <= n_elem; ++j) {
int mv = 0;
if(k > indices[j - 1]) {
k = indices[j - 1];
}
if(k != 1e9 && k < indices[j]) {
mv = less_before[j][indices[j]] - less_before[j][k] - less_before[i][indices[j]] + less_before[i][k] + 1;
}
dp_L[i][j] = mv + dp_L[i][j - 1];
}
}
int clogn = (int)ceil(log2(n_elem));
for(int i = 1; i <= n_elem; ++i) {
Segm_Elem *segm = new Segm_Elem[1 << (clogn + 1)]{};
deque<int> deq = deque<int>();
for(int j = 1; j <= n_elem; ++j) {
if(cnts[i][n_elem - j + 1] > 0) {
segm_update(segm, clogn, j - 1, Segm_Elem(0, 0, false, cnts[i][n_elem - j + 1], cnts[i][n_elem - j + 1]));
}
if(orig[j] > i) {
continue;
}
if(deq.empty() || orig[deq.back()] < orig[j]) {
deq.push_back(j);
}
}
int mn = 1e9;
for(int j = 0; j <= i - 1; ++j) {
while(!deq.empty() && orig[deq.front()] <= j) {
deq.pop_front();
}
if(j > 0) {
segm_update(segm, clogn, n_elem - indices[j], Segm_Elem(0, 0, true, cnts[i][indices[j]], cnts[i][indices[j]]));
}
int mv = 0;
if(j > 0 && !deq.empty()) {
int k = deq.front();
Segm_Elem ans = segm_query(segm, clogn, 0, n_elem - k);
int x = ans.sum;
mv = x;
}
mn = min(mn, dp[j] + dp_L[j + 1][i] + mv);
}
dp[i] = mn;
delete[] segm;
}
printf("%d\n", dp[n_elem]);
return 0;
}
Compilation message (stderr)
Main.cpp: In function 'int main()':
Main.cpp:105:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
105 | scanf("%d", &n_elem);
| ~~~~~^~~~~~~~~~~~~~~
Main.cpp:107:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
107 | scanf("%d", &orig[i]);
| ~~~~~^~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |