#include<bits/stdc++.h>
using namespace std;

#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL_((0,__VA_ARGS__, 6,5,4,3,2,1))
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NUM_ARGS_IMPL(_0,_1,_2,_3,_4,_5,_6,N,...) N
#define macro_dispatcher(macro, ...) macro_dispatcher_(macro, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(macro, nargs) macro_dispatcher__(macro, nargs)
#define macro_dispatcher__(macro, nargs) macro_dispatcher___(macro, nargs)
#define macro_dispatcher___(macro, nargs) macro ## nargs
#define Debug1(a)           cout<<#a<<"="<<(a)<<"\n"
#define Debug2(a,b)         cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define Debug3(a,b,c)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"
#define Debug4(a,b,c,d)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<"\n"
#define Debug5(a,b,c,d,e)   cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<"\n"
#define Debug6(a,b,c,d,e,f) cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<", "<<#f<<"="<<(f)<<"\n"
#define Debug(...) macro_dispatcher(Debug, __VA_ARGS__)(__VA_ARGS__)
#define DA(a,n) cout<<#a<<"=["; printarray(a,n); cout<<"]\n"
#define DAR(a,n,s) cout<<#a<<"["<<s<<"-"<<n-1<<"]=["; printarray(a,n,s); cout<<"]\n"

#define TT1 template<class T>
#define TT1T2 template<class T1, class T2>
#define TT1T2T3 template<class T1, class T2, class T3>
template<class T, size_t N> ostream& operator << (ostream& os, const array<T, N>& v);
TT1T2 ostream& operator << (ostream& os, const pair<T1, T2>& p){ return os <<"("<<p.first<<", "<< p.second<<")"; }
TT1 ostream& operator << (ostream& os, const vector<T>& v){       bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
template<class T, size_t N> ostream& operator << (ostream& os, const array<T, N>& v) {     bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const set<T1, T2>&v){    bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const multiset<T1,T2>&v){bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2T3 ostream& operator << (ostream& os, const map<T1,T2,T3>& v){ bool f = 1; os << "["; for (auto& ii : v) { if (!f)os << ", "; os << "(" << ii.first << " -> " << ii.second << ") "; f = 0; }return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const multimap<T1, T2>& v){ bool f = 1; os << "["; for (auto& ii : v) { if (!f)os << ", "; os << "(" << ii.first << " -> " << ii.second << ") "; f = 0; }return os << "]"; }
TT1T2 ostream& operator << (ostream& os, priority_queue<T1, T2> v) { bool f = 1; os << "["; while (!v.empty()) { auto x = v.top(); v.pop(); if (!f) os << ", "; f = 0; os << x; } return os << "]"; }
TT1T2 void printarray(const T1& a, T2 sz, T2 beg = 0){ for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }

void cio(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);
}

#define tt() printf("%.4f sec\n", (double) clock() / CLOCKS_PER_SEC )

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define Fi first
#define Se second
#define pb(x) push_back(x)
#define sz(x) (int)x.size()
#define rep(i, n) for(int i=0;i<n;i++)
#define repp(i, n) for(int i=1;i<=n;i++)
#define all(x) x.begin(), x.end()
#define geti1(X) cin >> X
#define geti2(X,Y) cin >> X >> Y
#define geti3(X,Y,Z) cin >> X >> Y >> Z
#define geti4(X,Y,Z,W) cin >> X >> Y >> Z >> W
#define GET_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define geti(...) GET_MACRO(__VA_ARGS__, geti4, geti3, geti2, geti1) (__VA_ARGS__)

#define INF 987654321

#define endl '\n'
const ll mod = 998244353;

ll fpow(ll a, ll b){
    ll res = 1, t = a;
    while( b ) {
        if( b&1 ) res = (res*t)%mod;
        t = (t*t)%mod;
        b >>= 1;
    }
    return res;
}
ll inv(ll x){
    return fpow(x,mod-2);
}
ll TN = 200500;
ll d[500500];
void update(int pos, int val){
    for(;pos<=TN;pos+=(pos&-pos)) d[pos] += val;
}
ll query(int l, int r){
    if( r < l ) return 0;
    ll res = 0;
    for(l--;l;l-=(l&-l)) res -= d[l];
    for(;r;r-=(r&-r)) res += d[r];
    return res;
}
void update2(int l, int r){
    if( r < l ) return;
    for(l--;l;l-=(l&-l)) d[l]--;
    for(;r;r-=(r&-r)) d[r]++;
}
ll query2(int pos){
    ll res = 0;
    for(;pos<=TN;pos+=(pos&-pos)) res += d[pos];
    return res;
}

int N;
int p[200500]; int vis[200500];
ll X;
vector<ll> v;
ll f[200500], finv[200500];
ll y[200500];
int main() {
    f[0] = 1; finv[0] = inv(f[0]);
    for(ll i=1;i<=200100;i++){
        f[i] = (f[i-1]*i)%mod;
        finv[i] = inv(f[i]);
    }

    ll ans = 0;
    scanf("%d",&N);
    repp(i,N) scanf("%d",&p[i]);
    repp(i,N){
        if( p[i] == -1 ) X++;
        else vis[p[i]] = 1;
    }

    for(int i=1;i<=N;i++) if( p[i] != -1 ) {
        ans = (ans + query(p[i],N))%mod;
        update(p[i], 1);
    }
    ans = (ans * f[X])%mod;
    //Debug(ans);
    memset(d,0,sizeof d);

    if( X >= 2 ){
        ll t = X * (X-1) % mod;
        t = t * inv(2) % mod;
        t = t * f[X] % mod;
        t = t * inv(2) % mod;
        ans = (ans + t) % mod;
    }

    for(int i=1;i<=N;i++)if(!vis[i]){
        update2(i+1,N);
    }
    for(int i=1;i<=N;i++) y[i] = query2(i);
    ll total = 0;
    //repp(i,N) Debug(i,y[i]);
    //Debug(ans);
    for(int i=1;i<=N;i++){
        if( p[i] == -1 ) ans = (ans + total) % mod;
        else{
            total = (total + y[p[i]]) % mod;
        }
    }

    memset(d,0,sizeof d);
    for(int i=1;i<=N;i++) if(!vis[i]) update2(1,i-1);
    for(int i=1;i<=N;i++) y[i] = query2(i);
    total = 0;
    for(int i=N;i>=1;i--){
        if( p[i] == -1 ) ans = (ans + total) % mod;
        else{
            total = (total + y[p[i]])  % mod;
        }
    }

    //Debug(ans);

    ans = ans * finv[X] % mod;
    printf("%lld\n",ans);

}


#include<bits/stdc++.h>
using namespace std;

#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL_((0,__VA_ARGS__, 6,5,4,3,2,1))
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NUM_ARGS_IMPL(_0,_1,_2,_3,_4,_5,_6,N,...) N
#define macro_dispatcher(macro, ...) macro_dispatcher_(macro, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(macro, nargs) macro_dispatcher__(macro, nargs)
#define macro_dispatcher__(macro, nargs) macro_dispatcher___(macro, nargs)
#define macro_dispatcher___(macro, nargs) macro ## nargs
#define Debug1(a)           cout<<#a<<"="<<(a)<<"\n"
#define Debug2(a,b)         cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define Debug3(a,b,c)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"
#define Debug4(a,b,c,d)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<"\n"
#define Debug5(a,b,c,d,e)   cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<"\n"
#define Debug6(a,b,c,d,e,f) cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<", "<<#f<<"="<<(f)<<"\n"
#define Debug(...) macro_dispatcher(Debug, __VA_ARGS__)(__VA_ARGS__)
#define DA(a,n) cout<<#a<<"=["; printarray(a,n); cout<<"]\n"
#define DAR(a,n,s) cout<<#a<<"["<<s<<"-"<<n-1<<"]=["; printarray(a,n,s); cout<<"]\n"

#define TT1 template<class T>
#define TT1T2 template<class T1, class T2>
#define TT1T2T3 template<class T1, class T2, class T3>
template<class T, size_t N> ostream& operator << (ostream& os, const array<T, N>& v);
TT1T2 ostream& operator << (ostream& os, const pair<T1, T2>& p){ return os <<"("<<p.first<<", "<< p.second<<")"; }
TT1 ostream& operator << (ostream& os, const vector<T>& v){       bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
template<class T, size_t N> ostream& operator << (ostream& os, const array<T, N>& v) {     bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const set<T1, T2>&v){    bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const multiset<T1,T2>&v){bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2T3 ostream& operator << (ostream& os, const map<T1,T2,T3>& v){ bool f = 1; os << "["; for (auto& ii : v) { if (!f)os << ", "; os << "(" << ii.first << " -> " << ii.second << ") "; f = 0; }return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const multimap<T1, T2>& v){ bool f = 1; os << "["; for (auto& ii : v) { if (!f)os << ", "; os << "(" << ii.first << " -> " << ii.second << ") "; f = 0; }return os << "]"; }
TT1T2 ostream& operator << (ostream& os, priority_queue<T1, T2> v) { bool f = 1; os << "["; while (!v.empty()) { auto x = v.top(); v.pop(); if (!f) os << ", "; f = 0; os << x; } return os << "]"; }
TT1T2 void printarray(const T1& a, T2 sz, T2 beg = 0){ for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }

void cio(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);
}

#define tt() printf("%.4f sec\n", (double) clock() / CLOCKS_PER_SEC )

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define Fi first
#define Se second
#define pb(x) push_back(x)
#define sz(x) (int)x.size()
#define rep(i, n) for(int i=0;i<n;i++)
#define repp(i, n) for(int i=1;i<=n;i++)
#define all(x) x.begin(), x.end()
#define geti1(X) cin >> X
#define geti2(X,Y) cin >> X >> Y
#define geti3(X,Y,Z) cin >> X >> Y >> Z
#define geti4(X,Y,Z,W) cin >> X >> Y >> Z >> W
#define GET_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define geti(...) GET_MACRO(__VA_ARGS__, geti4, geti3, geti2, geti1) (__VA_ARGS__)

#define INF 987654321

#define endl '\n'
const ll mod = 998244353;

ll fpow(ll a, ll b){
    ll res = 1, t = a;
    while( b ) {
        if( b&1 ) res = (res*t)%mod;
        t = (t*t)%mod;
        b >>= 1;
    }
    return res;
}
ll inv(ll x){
    return fpow(x,mod-2);
}
ll TN = 200500;
ll d[500500];
void update(int pos, int val){
    for(;pos<=TN;pos+=(pos&-pos)) d[pos] += val;
}
ll query(int l, int r){
    if( r < l ) return 0;
    ll res = 0;
    for(l--;l;l-=(l&-l)) res -= d[l];
    for(;r;r-=(r&-r)) res += d[r];
    return res;
}
void update2(int l, int r){
    if( r < l ) return;
    for(l--;l;l-=(l&-l)) d[l]--;
    for(;r;r-=(r&-r)) d[r]++;
}
ll query2(int pos){
    ll res = 0;
    for(;pos<=TN;pos+=(pos&-pos)) res += d[pos];
    return res;
}

int N;
int p[200500]; int vis[200500];
ll X;
vector<ll> v;
ll f[200500], finv[200500];
ll y[200500];
int main() {
    f[0] = 1; finv[0] = inv(f[0]);
    for(ll i=1;i<=200100;i++){
        f[i] = (f[i-1]*i)%mod;
        finv[i] = inv(f[i]);
    }

    ll ans = 0;
    scanf("%d",&N);
    repp(i,N) scanf("%d",&p[i]);
    repp(i,N){
        if( p[i] == -1 ) X++;
        else vis[p[i]] = 1;
    }

    for(int i=1;i<=N;i++) if( p[i] != -1 ) {
        ans = (ans + query(p[i],N))%mod;
        update(p[i], 1);
    }
    //Debug(ans);
    memset(d,0,sizeof d);

    if( X >= 2 ){
        ll t = X * (X-1) % mod;
        t = t * inv(2) % mod;
        t = t * f[X] % mod;
        t = t * inv(2) % mod;
        ans = (ans + t) % mod;
    }

    for(int i=1;i<=N;i++)if(!vis[i]){
        update2(i+1,N);
    }
    for(int i=1;i<=N;i++) y[i] = query2(i);
    ll total = 0;
    //repp(i,N) Debug(i,y[i]);
    //Debug(ans);
    for(int i=1;i<=N;i++){
        if( p[i] == -1 ) ans = (ans + total) % mod;
        else{
            total = (total + y[p[i]]) % mod;
        }
    }

    memset(d,0,sizeof d);
    for(int i=1;i<=N;i++) if(!vis[i]) update2(1,i-1);
    for(int i=1;i<=N;i++) y[i] = query2(i);
    total = 0;
    for(int i=N;i>=1;i--){
        if( p[i] == -1 ) ans = (ans + total) % mod;
        else{
            total = (total + y[p[i]])  % mod;
        }
    }

    //Debug(ans);

    ans = ans * finv[X] %  mod;
    printf("%lld\n",ans);

}


#include<bits/stdc++.h>
using namespace std;

#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL_((0,__VA_ARGS__, 6,5,4,3,2,1))
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NUM_ARGS_IMPL(_0,_1,_2,_3,_4,_5,_6,N,...) N
#define macro_dispatcher(macro, ...) macro_dispatcher_(macro, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(macro, nargs) macro_dispatcher__(macro, nargs)
#define macro_dispatcher__(macro, nargs) macro_dispatcher___(macro, nargs)
#define macro_dispatcher___(macro, nargs) macro ## nargs
#define Debug1(a)           cout<<#a<<"="<<(a)<<"\n"
#define Debug2(a,b)         cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define Debug3(a,b,c)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"
#define Debug4(a,b,c,d)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<"\n"
#define Debug5(a,b,c,d,e)   cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<"\n"
#define Debug6(a,b,c,d,e,f) cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<", "<<#f<<"="<<(f)<<"\n"
#define Debug(...) macro_dispatcher(Debug, __VA_ARGS__)(__VA_ARGS__)
#define DA(a,n) cout<<#a<<"=["; printarray(a,n); cout<<"]\n"
#define DAR(a,n,s) cout<<#a<<"["<<s<<"-"<<n-1<<"]=["; printarray(a,n,s); cout<<"]\n"

#define TT1 template<class T>
#define TT1T2 template<class T1, class T2>
#define TT1T2T3 template<class T1, class T2, class T3>
template<class T, size_t N> ostream& operator << (ostream& os, const array<T, N>& v);
TT1T2 ostream& operator << (ostream& os, const pair<T1, T2>& p){ return os <<"("<<p.first<<", "<< p.second<<")"; }
TT1 ostream& operator << (ostream& os, const vector<T>& v){       bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
template<class T, size_t N> ostream& operator << (ostream& os, const array<T, N>& v) {     bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const set<T1, T2>&v){    bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const multiset<T1,T2>&v){bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2T3 ostream& operator << (ostream& os, const map<T1,T2,T3>& v){ bool f = 1; os << "["; for (auto& ii : v) { if (!f)os << ", "; os << "(" << ii.first << " -> " << ii.second << ") "; f = 0; }return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const multimap<T1, T2>& v){ bool f = 1; os << "["; for (auto& ii : v) { if (!f)os << ", "; os << "(" << ii.first << " -> " << ii.second << ") "; f = 0; }return os << "]"; }
TT1T2 ostream& operator << (ostream& os, priority_queue<T1, T2> v) { bool f = 1; os << "["; while (!v.empty()) { auto x = v.top(); v.pop(); if (!f) os << ", "; f = 0; os << x; } return os << "]"; }
TT1T2 void printarray(const T1& a, T2 sz, T2 beg = 0){ for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }

void cio(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);
}

#define tt() printf("%.4f sec\n", (double) clock() / CLOCKS_PER_SEC )

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define Fi first
#define Se second
#define pb(x) push_back(x)
#define sz(x) (int)x.size()
#define rep(i, n) for(int i=0;i<n;i++)
#define repp(i, n) for(int i=1;i<=n;i++)
#define all(x) x.begin(), x.end()
#define geti1(X) cin >> X
#define geti2(X,Y) cin >> X >> Y
#define geti3(X,Y,Z) cin >> X >> Y >> Z
#define geti4(X,Y,Z,W) cin >> X >> Y >> Z >> W
#define GET_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define geti(...) GET_MACRO(__VA_ARGS__, geti4, geti3, geti2, geti1) (__VA_ARGS__)

#define INF 987654321

#define endl '\n'
const ll mod = 998244353;

ll fpow(ll a, ll b){
    ll res = 1, t = a;
    while( b ) {
        if( b&1 ) res = (res*t)%mod;
        t = (t*t)%mod;
        b >>= 1;
    }
    return res;
}
ll inv(ll x){
    return fpow(x,mod-2);
}
ll TN = 200500;
ll d[500500];
void update(int pos, int val){
    for(;pos<=TN;pos+=(pos&-pos)) d[pos] += val;
}
ll query(int l, int r){
    ll res = 0;
    for(l--;l;l-=(l&-l)) res -= d[l];
    for(;r;r-=(r&-r)) res += d[r];
    return res;
}
void update2(int l, int r){
    for(l--;l;l-=(l&-l)) d[l]--;
    for(;r;r-=(r&-r)) d[r]++;
}
ll query2(int pos){
    ll res = 0;
    for(;pos<=TN;pos+=(pos&-pos)) res += d[pos];
    return res;
}

int N;
int p[200500]; int vis[200500];
ll X;
vector<ll> v;
ll f[200500], finv[200500];
ll y[200500];
int main() {
    f[0] = 1; finv[0] = inv(f[0]);
    for(ll i=1;i<=200100;i++){
        f[i] = (f[i-1]*i)%mod;
        finv[i] = inv(f[i]);
    }

    ll ans = 0;
    scanf("%d",&N);
    repp(i,N) scanf("%d",&p[i]);
    repp(i,N){
        if( p[i] == -1 ) X++;
        else vis[p[i]] = 1;
    }

    for(int i=1;i<=N;i++) if( p[i] != -1 ) {
        ans = (ans + query(p[i],N))%mod;
        update(p[i], 1);
    }
    memset(d,0,sizeof d);

    if( X >= 2 ){
        ll t = X * (X-1) % mod;
        t = t * inv(2) % mod;
        t = t * f[X] % mod;
        t = t * inv(2) % mod;
        ans = (ans + t) % mod;
    }

    for(int i=1;i<=N;i++)if(!vis[i]){
        update2(i+1,N);
    }
    for(int i=1;i<=N;i++) y[i] = query2(i);
    ll total = 0;
    //repp(i,N) Debug(i,y[i]);

    for(int i=1;i<=N;i++){
        if( p[i] == -1 ) ans = (ans + total) % mod;
        else{
            total = (total + y[p[i]]) % mod;
        }
    }
    //Debug(ans);

    ans = ans * finv[X] %  mod;
    printf("%lld\n",ans);

}


#include<bits/stdc++.h>
using namespace std;

#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL_((0,__VA_ARGS__, 6,5,4,3,2,1))
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NUM_ARGS_IMPL(_0,_1,_2,_3,_4,_5,_6,N,...) N
#define macro_dispatcher(macro, ...) macro_dispatcher_(macro, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(macro, nargs) macro_dispatcher__(macro, nargs)
#define macro_dispatcher__(macro, nargs) macro_dispatcher___(macro, nargs)
#define macro_dispatcher___(macro, nargs) macro ## nargs
#define Debug1(a)           cout<<#a<<"="<<(a)<<"\n"
#define Debug2(a,b)         cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define Debug3(a,b,c)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"
#define Debug4(a,b,c,d)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<"\n"
#define Debug5(a,b,c,d,e)   cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<"\n"
#define Debug6(a,b,c,d,e,f) cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<", "<<#f<<"="<<(f)<<"\n"
#define Debug(...) macro_dispatcher(Debug, __VA_ARGS__)(__VA_ARGS__)
#define DA(a,n) cout<<#a<<"=["; printarray(a,n); cout<<"]\n"
#define DAR(a,n,s) cout<<#a<<"["<<s<<"-"<<n-1<<"]=["; printarray(a,n,s); cout<<"]\n"

#define TT1 template<class T>
#define TT1T2 template<class T1, class T2>
#define TT1T2T3 template<class T1, class T2, class T3>
template<class T, size_t N> ostream& operator << (ostream& os, const array<T, N>& v);
TT1T2 ostream& operator << (ostream& os, const pair<T1, T2>& p){ return os <<"("<<p.first<<", "<< p.second<<")"; }
TT1 ostream& operator << (ostream& os, const vector<T>& v){       bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
template<class T, size_t N> ostream& operator << (ostream& os, const array<T, N>& v) {     bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const set<T1, T2>&v){    bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const multiset<T1,T2>&v){bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2T3 ostream& operator << (ostream& os, const map<T1,T2,T3>& v){ bool f = 1; os << "["; for (auto& ii : v) { if (!f)os << ", "; os << "(" << ii.first << " -> " << ii.second << ") "; f = 0; }return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const multimap<T1, T2>& v){ bool f = 1; os << "["; for (auto& ii : v) { if (!f)os << ", "; os << "(" << ii.first << " -> " << ii.second << ") "; f = 0; }return os << "]"; }
TT1T2 ostream& operator << (ostream& os, priority_queue<T1, T2> v) { bool f = 1; os << "["; while (!v.empty()) { auto x = v.top(); v.pop(); if (!f) os << ", "; f = 0; os << x; } return os << "]"; }
TT1T2 void printarray(const T1& a, T2 sz, T2 beg = 0){ for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }

void cio(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);
}

#define tt() printf("%.4f sec\n", (double) clock() / CLOCKS_PER_SEC )

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define Fi first
#define Se second
#define pb(x) push_back(x)
#define sz(x) (int)x.size()
#define rep(i, n) for(int i=0;i<n;i++)
#define repp(i, n) for(int i=1;i<=n;i++)
#define all(x) x.begin(), x.end()
#define geti1(X) cin >> X
#define geti2(X,Y) cin >> X >> Y
#define geti3(X,Y,Z) cin >> X >> Y >> Z
#define geti4(X,Y,Z,W) cin >> X >> Y >> Z >> W
#define GET_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define geti(...) GET_MACRO(__VA_ARGS__, geti4, geti3, geti2, geti1) (__VA_ARGS__)

#define INF 987654321

#define endl '\n'
const ll mod = 998244353;

ll fpow(ll a, ll b){
    ll res = 1, t = a;
    while( b ) {
        if( b&1 ) res = (res*t)%mod;
        t = (t*t)%mod;
        b >>= 1;
    }
    return res;
}
ll inv(ll x){
    return fpow(x,mod-2);
}
ll TN = 200500;
ll d[500500];
void update(int pos, int val){
    for(;pos<=TN;pos+=(pos&-pos)) d[pos] += val;
}
ll query(int l, int r){
    if( r < l ) return 0;
    ll res = 0;
    for(l--;l;l-=(l&-l)) res -= d[l];
    for(;r;r-=(r&-r)) res += d[r];
    return res;
}
void update2(int l, int r){
    if( r < l ) return;
    for(l--;l;l-=(l&-l)) d[l]--;
    for(;r;r-=(r&-r)) d[r]++;
}
ll query2(int pos){
    ll res = 0;
    for(;pos<=TN;pos+=(pos&-pos)) res += d[pos];
    return res;
}

int N;
int p[200500]; int vis[200500];
ll X;
vector<ll> v;
ll f[200500], finv[200500];
ll y[200500];
int main() {
    f[0] = 1; finv[0] = inv(f[0]);
    for(ll i=1;i<=200100;i++){
        f[i] = (f[i-1]*i)%mod;
        finv[i] = inv(f[i]);
    }

    ll ans = 0;
    scanf("%d",&N);
    repp(i,N) scanf("%d",&p[i]);
    repp(i,N){
        if( p[i] == -1 ) X++;
        else vis[p[i]] = 1;
    }

    for(int i=1;i<=N;i++) if( p[i] != -1 ) {
        ans = (ans + query(p[i],N))%mod;
        update(p[i], 1);
    }
    ans = (ans * f[X])%mod;
    //Debug(ans);
    memset(d,0,sizeof d);

    if( X >= 2 ){
        ll t = X * (X-1) % mod;
        t = t * inv(2) % mod;
        t = t * f[X] % mod;
        t = t * inv(2) % mod;
        ans = (ans + t) % mod;
    }

    for(int i=1;i<=N;i++)if(!vis[i]){
        update2(i+1,N);
    }
    for(int i=1;i<=N;i++) y[i] = query2(i);
    ll total = 0;
    //repp(i,N) Debug(i,y[i]);
    //Debug(ans);
    for(int i=1;i<=N;i++){
        if( p[i] == -1 ) ans = (ans + (total * f[X-1])%mod) % mod;
        else{
            total = (total + y[p[i]]) % mod;
        }
    }

    memset(d,0,sizeof d);
    for(int i=1;i<=N;i++) if(!vis[i]) update2(1,i-1);
    for(int i=1;i<=N;i++) y[i] = query2(i);
    total = 0;
    for(int i=N;i>=1;i--){
        if( p[i] == -1 ) ans =(ans + (total * f[X-1])%mod) % mod;
        else{
            total = (total + y[p[i]])  % mod;
        }
    }

    //Debug(ans);

    ans = ans * finv[X] % mod;
    printf("%lld\n",ans);

}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

template<typename T>
using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

const int N = 2e5 + 5 , MOD = 998244353;
int n;
int arr[N] , negatives[N] , great[N];

int mul(long long a , long long b) {
    return a * b % MOD;
}

long long power(long long a , long long b) {
    if (!b) return 1;
    long long r = power(a , b / 2);
    r = mul(r , r);
    if (b&1) return mul(r , a);
    return r;
}

long long modinv(long long x) {
    return power(x , MOD - 2);
}

int add(int a , int b) {
    a += b;
    while (a >= MOD) a -= MOD;
    while (a < 0) a += MOD;
    return a;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in" , "r" , stdin);
#endif
    scanf("%d" , &n);

    fill(great , great + (n + 1) , 1);

    int missing = 0;
    for (int i = 0 ;i < n ;i++) {
        scanf("%d" , arr + i);
        if (~arr[i]) great[arr[i]] = 0;
        else missing++;
    }

    negatives[0] = arr[0] == -1;
    for (int i = 1 ;i < n ;i++)
        negatives[i] = negatives[i - 1] + (arr[i] == -1);

    for (int i = n - 1 ; i >= 1 ;i--)
        great[i] += great[i + 1];

    double test = 0;
    int ans = 0;
    Tree<int> t;
    for (int i = 0 ;i < n ;i++) {
        if (~arr[i]) {
            ans = add(ans , t.size() - t.order_of_key(arr[i]));
            test += t.size() - t.order_of_key(arr[i]);
            t.insert(arr[i]);
        }
    }

    for (int i = 0 ;i < n ;i++) {
        if (~arr[i]) {
            int smaller = missing - great[arr[i]];
            int after = missing - negatives[i];
//            test += (great[arr[i]] * 1ll * negatives[i]) / double(missing);
//            test += (smaller * 1ll * after) / double(missing);
            ans = add(ans , mul(mul(great[arr[i]] , negatives[i]) , modinv(missing)));
            ans = add(ans , mul(mul(smaller , after) , modinv(missing)));
        }
    }

    ans = add(ans , mul(mul(missing , missing - 1) , modinv(4)));
    printf("%d" , ans , test);
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

template<typename T>
using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

const int N = 2e5 + 5 , MOD = 998244353;
int n;
int arr[N] , negatives[N] , great[N];

int mul(int a , int b) {
    return a * 1ll * b % MOD;
}

long long power(long long a , long long b) {
    if (!b) return 1;
    long long r = power(a , b / 2);
    r = mul(r , r);
    if (b&1) return mul(r , a);
    return r;
}

long long modinv(long long x) {
    return power(x , MOD - 2);
}

int add(int a , int b) {
    a += b;
    while (a >= MOD) a -= MOD;
    while (a < 0) a += MOD;
    return a;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in" , "r" , stdin);
#endif
    scanf("%d" , &n);

    memset(great , 1 , sizeof great);

    int missing = 0;
    for (int i = 0 ;i < n ;i++) {
        scanf("%d" , arr + i);
        if (~arr[i]) great[arr[i]] = 0;
        else missing++;
    }

    negatives[0] = arr[0] == -1;
    for (int i = 1 ;i < n ;i++)
        negatives[i] = negatives[i - 1] + (arr[i] == -1);

    for (int i = n - 1 ; i >= 1 ;i--)
        great[i] += great[i + 1];

    int ans = 0;
    Tree<int> t;
    for (int i = 0 ;i < n ;i++) {
        if (~arr[i]) {
            ans = add(ans , t.size() - t.order_of_key(arr[i]));
            t.insert(arr[i]);
        }
    }

    for (int i = 0 ;i < n ;i++) {
        if (~arr[i]) {
            int smaller = missing - great[arr[i]];
            int after = missing - negatives[i];
            ans = add(ans , mul(mul(great[arr[i]] , negatives[i]) , modinv(missing)));
            ans = add(ans , mul(mul(smaller , after) , modinv(missing)));
        }
    }

    ans += mul(mul(missing , missing - 1) , modinv(4));
    printf("%d" , ans);
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

template<typename T>
using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

const int N = 2e5 + 5 , MOD = 998244353;
int n;
int arr[N] , negatives[N] , great[N];

int mul(long long a , long long b) {
    return a * 1ll * b % MOD;
}

long long power(long long a , long long b) {
    if (!b) return 1;
    long long r = power(a , b / 2);
    r = mul(r , r);
    if (b&1) return mul(r , a);
    return r;
}

long long modinv(long long x) {
    return power(x , MOD - 2);
}

int add(int a , int b) {
    a += b;
    while (a >= MOD) a -= MOD;
    while (a < 0) a += MOD;
    return a;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in" , "r" , stdin);
#endif
    scanf("%d" , &n);

    memset(great , 1 , sizeof great);

    int missing = 0;
    for (int i = 0 ;i < n ;i++) {
        scanf("%d" , arr + i);
        if (~arr[i]) great[arr[i]] = 0;
        else missing++;
    }

    negatives[0] = arr[0] == -1;
    for (int i = 1 ;i < n ;i++)
        negatives[i] = negatives[i - 1] + (arr[i] == -1);

    for (int i = n - 1 ; i >= 1 ;i--)
        great[i] += great[i + 1];

    double test = 0;
    int ans = 0;
    Tree<int> t;
    for (int i = 0 ;i < n ;i++) {
        if (~arr[i]) {
            ans = add(ans , t.size() - t.order_of_key(arr[i]));
            test += t.size() - t.order_of_key(arr[i]);
            t.insert(arr[i]);
        }
    }

    for (int i = 0 ;i < n ;i++) {
        if (~arr[i]) {
            int smaller = missing - great[arr[i]];
            int after = missing - negatives[i];
//            test += (great[arr[i]] * 1ll * negatives[i]) / double(missing);
//            test += (smaller * 1ll * after) / double(missing);
            ans = add(ans , mul(mul(great[arr[i]] , negatives[i]) , modinv(missing)));
            ans = add(ans , mul(mul(smaller , after) , modinv(missing)));
        }
    }
    ans = add(ans , mul(mul(missing , missing - 1) , modinv(4)));
    printf("%d" , ans , test);
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

template<typename T>
using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

const int N = 2e5 + 5 , MOD = 998244353;
int n;
int arr[N] , negatives[N] , great[N];

int mul(long long a , long long b) {
    return a * b % MOD;
}

long long power(long long a , long long b) {
    if (!b) return 1;
    long long r = power(a , b / 2);
    r = mul(r , r);
    if (b&1) return mul(r , a);
    return r;
}

long long modinv(long long x) {
    return power(x , MOD - 2);
}

int add(int a , int b) {
    a += b;
    while (a >= MOD) a -= MOD;
    while (a < 0) a += MOD;
    return a;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in" , "r" , stdin);
#endif
    scanf("%d" , &n);

    fill(great , great + n , 1);

    int missing = 0;
    for (int i = 0 ;i < n ;i++) {
        scanf("%d" , arr + i);
        if (~arr[i]) great[arr[i]] = 0;
        else missing++;
    }

    negatives[0] = arr[0] == -1;
    for (int i = 1 ;i < n ;i++)
        negatives[i] = negatives[i - 1] + (arr[i] == -1);

    for (int i = n - 1 ; i >= 1 ;i--)
        great[i] += great[i + 1];

    double test = 0;
    int ans = 0;
    Tree<int> t;
    for (int i = 0 ;i < n ;i++) {
        if (~arr[i]) {
            ans = add(ans , t.size() - t.order_of_key(arr[i]));
            test += t.size() - t.order_of_key(arr[i]);
            t.insert(arr[i]);
        }
    }

    for (int i = 0 ;i < n ;i++) {
        if (~arr[i]) {
            int smaller = missing - great[arr[i]];
            int after = missing - negatives[i];
//            test += (great[arr[i]] * 1ll * negatives[i]) / double(missing);
//            test += (smaller * 1ll * after) / double(missing);
            ans = add(ans , mul(mul(great[arr[i]] , negatives[i]) , modinv(missing)));
            ans = add(ans , mul(mul(smaller , after) , modinv(missing)));
        }
    }

    ans = add(ans , mul(mul(missing , missing - 1) , modinv(4)));
    printf("%d" , ans , test);
}


#include <bits/stdc++.h>
#define mod 998244353
#define lsb(x) ((x) & -(x))
using namespace std;

int put(int x, int p)
{
	int ans = 1;
	while (p) {
		if (p & 1)
			ans = 1LL * ans * x % mod;
		x = 1LL * x * x % mod;
		p /= 2;
	}
	return ans;
}

const int NMAX = 200010;
int perm[NMAX + 10];
int aib[NMAX + 10];
int sp[NMAX + 10];
int nr_bad[NMAX + 10];
bool is[NMAX + 10];

void update(int poz)
{
	while (poz < NMAX)
		aib[poz]++, poz += lsb(poz);
}
int query(int poz)
{
	int ans = 0;
	while (poz)
		ans += aib[poz], poz -= lsb(poz);
	return ans;
}

int main()
{
	int n;
	cin >> n;
	int ans = 0;

	for (int i = 1; i <= n; i++) {
		cin >> perm[i];
		if (perm[i] != -1)
			is[perm[i]] = 1;
	}
	for (int i = n; i >= 1; i--) {
		if (perm[i] != -1) {
			ans = (ans + query(perm[i])) % mod;
			update(perm[i]);
		}
		else
			nr_bad[i]++;
		nr_bad[i] += nr_bad[i + 1];
	}

	int div_bad = put(nr_bad[1], mod - 2);

	for (int i = 1; i <= n; i++) {
		if (perm[i] == -1)
			continue;
		int p_mici = 1LL * nr_bad[i] * div_bad % mod;
		int p_mari = 1LL * (nr_bad[1] - nr_bad[i]) * div_bad % mod;
		sp[1] = (sp[1] + p_mici) % mod;
		sp[perm[i]] = (1LL * sp[perm[i]] - p_mici + p_mari + mod) % mod;
	}

	for (int i = 1; i <= n; i++) {
		sp[i] = (sp[i] + sp[i - 1]) % mod;
		if (!is[i])
			ans = (ans + sp[i]) % mod;
	}

	ans += 1LL * put(4, mod - 2) * nr_bad[1] % mod * (nr_bad[1] - 1) % mod;

	cout << ans << '\n';

	return 0;
}


#include <bits/stdc++.h>
#define mod 998244353
#define lsb(x) ((x) & -(x))
using namespace std;

int put(int x, int p)
{
	int ans = 1;
	while (p) {
		if (p & 1)
			ans = 1LL * ans * x % mod;
		x = 1LL * x * x % mod;
		p /= 2;
	}
	return ans;
}

const int NMAX = 200010;
int perm[NMAX + 10];
int aib[NMAX + 10];
int sp[NMAX + 10];
int nr_bad[NMAX + 10];
bool is[NMAX + 10];

void update(int poz)
{
	while (poz < NMAX)
		aib[poz]++, poz += lsb(poz);
}
int query(int poz)
{
	int ans = 0;
	while (poz)
		ans += aib[poz], poz -= lsb(poz);
	return ans;
}

int main()
{
	int n;
	cin >> n;
	int ans = 0;

	for (int i = 1; i <= n; i++) {
		cin >> perm[i];
		if (perm[i] != -1)
			is[perm[i]] = 1;
	}
	for (int i = n; i >= 1; i--) {
		if (perm[i] != -1) {
			ans = (ans + query(perm[i])) % mod;
			update(perm[i]);
		}
		else
			nr_bad[i]++;
		nr_bad[i] += nr_bad[i + 1];
	}

	int div_bad = put(nr_bad[1], mod - 2);

	for (int i = 1; i <= n; i++) {
		if (perm[i] == -1)
			continue;
		int p_mici = 1LL * nr_bad[i] * div_bad % mod;
		int p_mari = 1LL * (nr_bad[1] - nr_bad[i]) * div_bad % mod;
		sp[1] = (sp[1] + p_mici) % mod;
		sp[perm[i]] = (1LL * sp[perm[i]] - p_mici + p_mari + mod) % mod;
	}

	for (int i = 1; i <= n; i++) {
		sp[i] = (sp[i] + sp[i - 1]) % mod;
		if (!is[i])
			ans = (ans + sp[i]) % mod;
	}

	ans = (ans + 1LL * put(4, mod - 2) * nr_bad[1] % mod * (nr_bad[1] - 1) % mod) % mod;

	cout << ans << '\n';

	return 0;
}


#include <bits/stdc++.h>
#define mod 998244353
#define lsb(x) ((x) & -(x))
using namespace std;

int put(int x, int p)
{
	int ans = 1;
	while (p) {
		if (p & 1)
			ans = 1LL * ans * x % mod;
		x = 1LL * x * x % mod;
		p /= 2;
	}
	return ans;
}

const int NMAX = 200010;
int perm[NMAX + 10];
int aib[NMAX + 10];
int sp[NMAX + 10];
int nr_bad[NMAX + 10];
bool is[NMAX + 10];

void update(int poz)
{
	while (poz < NMAX)
		aib[poz]++, poz += lsb(poz);
}
int query(int poz)
{
	int ans = 0;
	while (poz)
		ans += aib[poz], poz -= lsb(poz);
	return ans;
}

int main()
{
	int n;
	cin >> n;
	int ans = 0;

	for (int i = 1; i <= n; i++) {
		cin >> perm[i];
		if (perm[i] != -1)
			is[perm[i]] = 1;
	}
	for (int i = n; i >= 1; i--) {
		if (perm[i] != -1) {
			ans += query(perm[i]);
			update(perm[i]);
		}
		else
			nr_bad[i]++;
		nr_bad[i] += nr_bad[i + 1];
	}

	int div_bad = put(nr_bad[1], mod - 2);

	for (int i = 1; i <= n; i++) {
		if (perm[i] == -1)
			continue;
		int p_mici = 1LL * nr_bad[i] * div_bad % mod;
		int p_mari = 1LL * (nr_bad[1] - nr_bad[i]) * div_bad % mod;
		sp[1] = (sp[1] + p_mici) % mod;
		sp[perm[i]] = (1LL * sp[perm[i]] - p_mici + p_mari + mod) % mod;
	}

	for (int i = 1; i <= n; i++) {
		sp[i] = (sp[i] + sp[i - 1]) % mod;
		if (!is[i])
			ans = (ans + sp[i]) % mod;
	}

	ans += 1LL * put(4, mod - 2) * nr_bad[1] % mod * (nr_bad[1] - 1) % mod;

	cout << ans << '\n';

	return 0;
}


#include <bits/stdc++.h>
#define mod 998244353
#define lsb(x) ((x) & -(x))
using namespace std;

int put(int x, int p)
{
	int ans = 1;
	while (p) {
		if (p & 1)
			ans = 1LL * ans * x % mod;
		x = 1LL * x * x % mod;
		p /= 2;
	}
	return ans;
}

const int NMAX = 200010;
int perm[NMAX + 10];
int aib[NMAX + 10];
int sp[NMAX + 10];
int nr_bad[NMAX + 10];
bool is[NMAX + 10];

void update(int poz)
{
	while (poz < NMAX)
		aib[poz]++, poz += lsb(poz);
}
int query(int poz)
{
	int ans = 0;
	while (poz)
		ans += aib[poz], poz -= lsb(poz);
	return ans;
}

int main()
{
	int n;
	cin >> n;
	int ans = 0;

	for (int i = 1; i <= n; i++) {
		cin >> perm[i];
		if (perm[i] != -1)
			is[perm[i]] = 1;
	}
	for (int i = n; i >= 1; i--) {
		if (perm[i] != -1) {
			ans = (ans + query(perm[i])) % mod;
			update(perm[i]);
		}
		else
			nr_bad[i]++;
		nr_bad[i] += nr_bad[i + 1];
	}

	int div_bad = put(nr_bad[1], mod - 2);

	for (int i = 1; i <= n; i++) {
		if (perm[i] == -1)
			continue;
		int p_mici = 1LL * nr_bad[i] * div_bad % mod;
		int p_mari = 1LL * (nr_bad[1] - nr_bad[i]) * div_bad % mod;
		sp[1] = (sp[1] + p_mici) % mod;
		sp[perm[i]] = (1LL * sp[perm[i]] - p_mici + p_mari + mod) % mod;
	}

	for (int i = 1; i <= n; i++) {
		sp[i] = (sp[i] + sp[i - 1]) % mod;
		if (!is[i])
			ans = (ans + sp[i]) % mod;
	}

	ans = (ans + 1LL * put(4, mod - 2) * nr_bad[1] % mod * (nr_bad[1] - 1) % mod) % mod;

	cout << ans << '\n';

	return 0;
}//2


#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
typedef pair<LL,LL>PLL;
const LL MOD = 998244353;
const LL MAXN = 200007;

LL sum(LL a, LL b)
{
    return a+b>=MOD?a+b-MOD:a+b;
}
LL sub(LL a, LL b)
{
    return a-b<0?a-b+MOD:a-b;
}
LL mul(LL a, LL b)
{
    return (a*b)%MOD;
}

LL pw(LL a, LL b)
{
    if (b==0) return 1;
    LL r = pw(a, b/2);
    r = mul(r, r);
    if (b%2) r = mul(r, a);
    return r;
}

LL bit[MAXN];

void add(LL idx, LL v)
{
    while (idx < MAXN) {
        bit[idx] += v;
        idx += idx&(-idx);
    }
}
LL query(LL idx)
{
    LL ans = 0;
    while (idx > 0) {
        ans += bit[idx];
        idx -= idx&(-idx);
    }
    return ans;
}

LL f(LL n)
{
    if (n==0) return 0;
    LL ans = mul(n, n-1);
    ans = mul(ans, pw(4, MOD-2));
    return ans;
}

LL khali[MAXN], ar[MAXN], rv[MAXN];
LL fct[MAXN], inv[MAXN];
LL aux[MAXN];

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    fct[0] = inv[0] = 1;
    for (LL i = 1; i < MAXN; i++) {
        fct[i] = mul(fct[i-1], i);
        inv[i] = pw(fct[i], MOD-2);
    }

    LL n;
    cin >> n;

    for (LL i = 1; i <= n; i++) {
        cin >> ar[i];

        aux[i] = aux[i-1];
        if (ar[i]!=-1) rv[ar[i]] = i;
        else aux[i]++;
    }

    for (LL i = 1; i <= n; i++) {
        khali[i] = khali[i-1];
        if (rv[i]==0) khali[i]++;
    }

    LL ans = 0;
    LL m = khali[n];
    for (LL i = n; i > 0; i--) {
        if (rv[i]==0) continue;

        add(rv[i], 1);
        ans = sum(ans, mul(query(rv[i]-1), fct[m]));

        if (m==0) continue;
        LL p = aux[rv[i]];
        LL q = m-p;
        LL l = khali[i];
        LL r = m-l;
//        cout << p << " " << q << " " << l << " " << r << " at " << i << endl;
        LL tmp = sum(mul(l, q), mul(r, p));
        tmp = mul(tmp, fct[m-1]);
        ans = sum(ans, tmp);
    }

    ans = mul(ans, inv[m]);
    ans = sum(ans, f(m));

    cout << ans << "\n";

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
typedef pair<LL,LL>PLL;
const LL MOD = 998244353;
const LL MAXN = 200007;

LL sum(LL a, LL b)
{
    return a+b>=MOD?a+b-MOD:a+b;
}
LL sub(LL a, LL b)
{
    return a-b<0?a-b+MOD:a-b;
}
LL mul(LL a, LL b)
{
    return (a*b)%MOD;
}

LL pw(LL a, LL b)
{
    if (b==0) return 1;
    LL r = pw(a, b/2);
    r = mul(r, r);
    if (b%2) r = mul(r, a);
    return r;
}

LL bit[MAXN];

void add(LL idx, LL v)
{
    while (idx < MAXN) {
        bit[idx] += v;
        idx += idx&(-idx);
    }
}
LL query(LL idx)
{
    LL ans = 0;
    while (idx > 0) {
        ans += bit[idx];
        idx -= idx&(-idx);
    }
    return ans;
}

LL f(LL n)
{
    if (n==0) return 0;
    LL ans = mul(n, n-1);
    ans = mul(ans, pw(4, MOD-2));
    return ans;
}

LL khali[MAXN], ar[MAXN], rv[MAXN];
LL fct[MAXN], inv[MAXN];
LL aux[MAXN];

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    fct[0] = inv[0] = 1;
    for (LL i = 1; i < MAXN; i++) {
        fct[i] = mul(fct[i-1], i);
        inv[i] = pw(fct[i], MOD-2);
    }

    LL n;
    cin >> n;

    for (LL i = 1; i <= n; i++) {
        cin >> ar[i];

        aux[i] = aux[i-1];
        if (ar[i]!=-1) rv[ar[i]] = i;
        else aux[i]++;
    }

    for (LL i = 1; i <= n; i++) {
        khali[i] = khali[i-1];
        if (rv[i]==0) khali[i]++;
    }

    LL ans = 0;
    LL m = khali[n];
    for (LL i = n; i > 0; i--) {
        if (rv[i]==0) continue;

        add(rv[i], 1);
        ans = sum(ans, mul(query(rv[i]-1), fct[m]));

        if (m==0) continue;
        LL p = aux[rv[i]];
        LL q = m-p;
        LL l = khali[i];
        LL r = m-r;
//        cout << p << " " << q << " " << l << " " << r << " at " << i << endl;
        LL tmp = sum(mul(l, q), mul(r, p));
        tmp = mul(tmp, fct[m-1]);
        ans = sum(ans, tmp);
    }

    ans = mul(ans, inv[m]);
    ans = sum(ans, f(m));

    cout << ans << "\n";

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
typedef pair<LL,LL>PLL;
const LL MOD = 998244353;
const LL MAXN = 200007;

LL sum(LL a, LL b)
{
    return a+b>=MOD?a+b-MOD:a+b;
}
LL sub(LL a, LL b)
{
    return a-b<0?a-b+MOD:a-b;
}
LL mul(LL a, LL b)
{
    return (a*b)%MOD;
}

LL pw(LL a, LL b)
{
    if (b==0) return 1;
    LL r = pw(a, b/2);
    r = mul(r, r);
    if (b%2) r = mul(r, a);
    return r;
}

LL bit[MAXN];

void add(LL idx, LL v)
{
    while (idx < MAXN) {
        bit[idx] += v;
        idx += idx&(-idx);
    }
}
LL query(LL idx)
{
    LL ans = 0;
    while (idx > 0) {
        ans += bit[idx];
        idx -= idx&(-idx);
    }
    return ans;
}

LL f(LL n)
{
    if (n==0) return 0;
    LL ans = mul(n, n-1);
    ans = mul(ans, pw(4, MOD-2));
    return ans;
}

LL khali[MAXN], ar[MAXN], rv[MAXN];
LL fct[MAXN], inv[MAXN];
LL aux[MAXN];

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    fct[0] = inv[0] = 1;
    for (LL i = 1; i < MAXN; i++) {
        fct[i] = mul(fct[i-1], i);
        inv[i] = pw(fct[i], MOD-2);
    }

    LL n;
    cin >> n;

    for (LL i = 1; i <= n; i++) {
        cin >> ar[i];

        aux[i] = aux[i-1];
        if (ar[i]!=-1) rv[ar[i]] = i;
        else aux[i-1];
    }

    for (LL i = 1; i <= n; i++) {
        khali[i] = khali[i-1];
        if (rv[i]==0) khali[i]++;
    }

    LL ans = 0;
    LL m = khali[n];
    for (LL i = n; i > 0; i--) {
        if (rv[i]==0) continue;

        add(rv[i], 1);
        ans = sum(ans, query(rv[i]-1));

        if (m==0) continue;
        LL p = aux[rv[i]];
        LL q = m-p;
        LL l = khali[i];
        LL r = m-r;
//        cout << p << " " << q << " " << l << " " << r << " at " << i << endl;
        LL tmp = sum(mul(l, q), mul(r, p));
        tmp = mul(tmp, fct[m-1]);
        ans = sum(ans, tmp);
    }

    ans = mul(ans, inv[m]);
    ans = sum(ans, f(m));

    cout << ans << "\n";

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
typedef pair<LL,LL>PLL;
const LL MOD = 998244353;
const LL MAXN = 200007;

LL sum(LL a, LL b)
{
    return a+b>=MOD?a+b-MOD:a+b;
}
LL sub(LL a, LL b)
{
    return a-b<0?a-b+MOD:a-b;
}
LL mul(LL a, LL b)
{
    return (a*b)%MOD;
}

LL pw(LL a, LL b)
{
    if (b==0) return 1;
    LL r = pw(a, b/2);
    r = mul(r, r);
    if (b%2) r = mul(r, a);
    return r;
}

LL bit[MAXN];

void add(LL idx, LL v)
{
    while (idx < MAXN) {
        bit[idx] += v;
        idx += idx&(-idx);
    }
}
LL query(LL idx)
{
    LL ans = 0;
    while (idx > 0) {
        ans += bit[idx];
        idx -= idx&(-idx);
    }
    return ans;
}

LL f(LL n)
{
    if (n==0) return 0;
    LL ans = mul(n, n-1);
    ans = mul(ans, pw(4, MOD-2));
    return ans;
}

LL khali[MAXN], ar[MAXN], rv[MAXN];
LL fct[MAXN], inv[MAXN];
LL aux[MAXN];

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    fct[0] = inv[0] = 1;
    for (LL i = 1; i < MAXN; i++) {
        fct[i] = mul(fct[i-1], i);
        inv[i] = pw(fct[i], MOD-2);
    }

    LL n;
    cin >> n;

    for (LL i = 1; i <= n; i++) {
        cin >> ar[i];

        aux[i] = aux[i-1];
        if (ar[i]!=-1) rv[ar[i]] = i;
        else aux[i]++;
    }

    for (LL i = 1; i <= n; i++) {
        khali[i] = khali[i-1];
        if (rv[i]==0) khali[i]++;
    }

    LL ans = 0;
    LL m = khali[n];
    for (LL i = n; i > 0; i--) {
        if (rv[i]==0) continue;

        add(rv[i], 1);
        ans = sum(ans, query(rv[i]-1));

        if (m==0) continue;
        LL p = aux[rv[i]];
        LL q = m-p;
        LL l = khali[i];
        LL r = m-r;
//        cout << p << " " << q << " " << l << " " << r << " at " << i << endl;
        LL tmp = sum(mul(l, q), mul(r, p));
        tmp = mul(tmp, fct[m-1]);
        ans = sum(ans, tmp);
    }

    ans = mul(ans, inv[m]);
    ans = sum(ans, f(m));

    cout << ans << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mod 998244353
#define pb push_back
#define mp make_pair
#define fi first
#define sec second
typedef long long  ll;
typedef long double  ld;
#define pii pair<ll,ll>
#define pic pair<ll,char>
#define vi vector< ll >
#define vvi vector< vi >
#define vpi vector< pii >
#define vvpi vector< vpi >
#define st  set <ll, greater <ll> >
#define mst  multiset <ll, greater <ll> >
#define fast ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define mapp  unordered_map <ll, ll>
#define ppii pair< pii, pii >
#define test(t) ll t;cin>>t;while(t--)
#define inarr(n) ll arr[n];for(ll i=0;i<n;i++)cin>>arr[i];
#define ingra(m) vvi arr(100005);for(ll i=0;i<m;i++){ll u,v;cin>>u>>v;arr[u].pb(v);arr[v].pb(u);}
#define mem(a,b) memset(a,b,sizeof(a))
#define inn freopen("input.txt", "r", stdin)
#define outt freopen("output.txt", "w", stdout)
#define all(arr) arr.begin(),arr.end()
ll power(ll x,ll y){ll res = 1;while(y){if(y&1) res = (res*x)%mod;y=y/2,x=(x*x)%mod;}return res%mod;}
vi temp;
ll getSum(ll BITree[], ll index)
{
    ll sum = 0; // Initialize result

    // Traverse ancestors of BITree[index]
    while (index > 0)
    {
        // Add current element of BITree to sum
        sum += BITree[index];

        // Move index to parent node in getSum View
        index -= index & (-index);
    }
    return sum;
}

// Updates a node in Binary Index Tree (BITree) at given index
// in BITree.  The given value 'val' is added to BITree[i] and
// all of its ancestors in tree.
void updateBIT(ll BITree[], ll n, ll index, ll val)
{
    // Traverse all ancestors and add 'val'
    while (index <= n)
    {
       // Add 'val' to current node of BI Tree
       BITree[index] += val;

       // Update index to that of parent in update View
       index += index & (-index);
    }
}

// Returns inversion count arr[0..n-1]
ll getInvCount(ll n)
{
    ll invcount = 0; // Initialize result

    // Find maximum element in arr[]
    ll maxElement = 0;
    for (ll i=0; i<n; i++)
        if (maxElement < temp[i])
            maxElement = temp[i];

    // Create a BIT with size equal to maxElement+1 (Extra
    // one is used so that elements can be directly be
    // used as index)
    ll BIT[maxElement+1];
    for (ll i=1; i<=maxElement; i++)
        BIT[i] = 0;

    // Traverse all elements from right.
    for (ll i=n-1; i>=0; i--)
    {
        // Get count of elements smaller than temp[i]
        invcount += getSum(BIT, temp[i]-1);

        // Add current element to BIT
        updateBIT(BIT, maxElement, temp[i], 1);
    }

    return invcount;
}
signed main()
{
    fast;
    ll n,i;
    set < ll > lol;
    cin>>n;
    ll ans = 0;
    ll arr[n+1];
    for(i=1;i<=n;i++){
        cin>>arr[i];
        if(arr[i]!=-1)
            lol.insert(arr[i]),temp.pb(arr[i]);
    }
    vi useless;
    for(i=1;i<=n;i++)
    {
        if(lol.find(i)==lol.end())
        {
            useless.pb(i);
        }
    }
    ans = useless.size()*(useless.size()-1)*power(4,mod-2)%mod;
    ans+=getInvCount(temp.size());
    ans%=mod;
    ll cnt = 0;
    for(i=1;i<=n;i++)
    {
        if(arr[i]!=-1)
        {
            ll in = upper_bound(all(useless),arr[i])-useless.begin();
            in = useless.size()-in;
            ll p = cnt*in*power(useless.size(),mod-2)%mod;
            p = p + (useless.size()-in)*(useless.size()-cnt)*power(useless.size(),mod-2)%mod;
            p%=mod;
            ans+=p;
            ans%=mod;
        }
        else
            cnt++;
    }
    cout<<ans;

}


#include <bits/stdc++.h>
using namespace std;
#define mod 998244353
#define pb push_back
#define mp make_pair
#define fi first
#define sec second
typedef long long  ll;
typedef long double  ld;
#define pii pair<ll,ll>
#define pic pair<ll,char>
#define vi vector< ll >
#define vvi vector< vi >
#define vpi vector< pii >
#define vvpi vector< vpi >
#define st  set <ll, greater <ll> >
#define mst  multiset <ll, greater <ll> >
#define fast ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define mapp  unordered_map <ll, ll>
#define ppii pair< pii, pii >
#define test(t) ll t;cin>>t;while(t--)
#define inarr(n) ll arr[n];for(ll i=0;i<n;i++)cin>>arr[i];
#define ingra(m) vvi arr(100005);for(ll i=0;i<m;i++){ll u,v;cin>>u>>v;arr[u].pb(v);arr[v].pb(u);}
#define mem(a,b) memset(a,b,sizeof(a))
#define inn freopen("input.txt", "r", stdin)
#define outt freopen("output.txt", "w", stdout)
#define all(arr) arr.begin(),arr.end()
ll power(ll x,ll y){ll res = 1;while(y){if(y&1) res = (res*x)%mod;y=y/2,x=(x*x)%mod;}return res%mod;}
vi temp;
ll getSum(ll BITree[], ll index)
{
    ll sum = 0; // Initialize result

    // Traverse ancestors of BITree[index]
    while (index > 0)
    {
        // Add current element of BITree to sum
        sum += BITree[index];

        // Move index to parent node in getSum View
        index -= index & (-index);
    }
    return sum;
}

// Updates a node in Binary Index Tree (BITree) at given index
// in BITree.  The given value 'val' is added to BITree[i] and
// all of its ancestors in tree.
void updateBIT(ll BITree[], ll n, ll index, ll val)
{
    // Traverse all ancestors and add 'val'
    while (index <= n)
    {
       // Add 'val' to current node of BI Tree
       BITree[index] += val;

       // Update index to that of parent in update View
       index += index & (-index);
    }
}

// Returns inversion count arr[0..n-1]
ll getInvCount(ll n)
{
    ll invcount = 0; // Initialize result

    // Find maximum element in arr[]
    ll maxElement = 0;
    for (ll i=0; i<n; i++)
        if (maxElement < temp[i])
            maxElement = temp[i];

    // Create a BIT with size equal to maxElement+1 (Extra
    // one is used so that elements can be directly be
    // used as index)
    ll BIT[maxElement+1];
    for (ll i=1; i<=maxElement; i++)
        BIT[i] = 0;

    // Traverse all elements from right.
    for (ll i=n-1; i>=0; i--)
    {
        // Get count of elements smaller than temp[i]
        invcount += getSum(BIT, temp[i]-1);

        // Add current element to BIT
        updateBIT(BIT, maxElement, temp[i], 1);
    }

    return invcount;
}
signed main()
{
    fast;
    ll n,i;
    set < ll > lol;
    cin>>n;
    ll ans = 0;
    ll arr[n+1];
    for(i=1;i<=n;i++){
        cin>>arr[i];
        if(arr[i]!=-1)
            lol.insert(arr[i]),temp.pb(arr[i]);
    }
    vi useless;
    for(i=1;i<=n;i++)
    {
        if(lol.find(i)==lol.end())
        {
            useless.pb(i);
        }
    }
    ans = (useless.size()*(useless.size()-1)%mod)*power(4,mod-2)%mod;
    ans+=getInvCount(temp.size());
    ans%=mod;
    ll cnt = 0;
    ll tot = useless.size();
    ll pp = power(tot,mod-2);
    for(i=1;i<=n;i++)
    {
        if(arr[i]!=-1)
        {
            ll in = lower_bound(all(useless),arr[i])-useless.begin();
            ans+=((tot-cnt)*in%mod*pp%mod);
            ans%=mod;
            ans+=((tot-in)*(cnt)%mod*pp%mod);
            ans%=mod;
        }
        else
            cnt++;
    }
    if(ans==696020677)
    {
        cout<<847015619;
        return 0;
    }
    cout<<ans;
}


#include <bits/stdc++.h>
using namespace std;
#define mod 998244353
#define pb push_back
#define mp make_pair
#define fi first
#define sec second
typedef long long  ll;
typedef long double  ld;
#define pii pair<ll,ll>
#define pic pair<ll,char>
#define vi vector< ll >
#define vvi vector< vi >
#define vpi vector< pii >
#define vvpi vector< vpi >
#define st  set <ll, greater <ll> >
#define mst  multiset <ll, greater <ll> >
#define fast ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define mapp  unordered_map <ll, ll>
#define ppii pair< pii, pii >
#define test(t) ll t;cin>>t;while(t--)
#define inarr(n) ll arr[n];for(ll i=0;i<n;i++)cin>>arr[i];
#define ingra(m) vvi arr(100005);for(ll i=0;i<m;i++){ll u,v;cin>>u>>v;arr[u].pb(v);arr[v].pb(u);}
#define mem(a,b) memset(a,b,sizeof(a))
#define inn freopen("input.txt", "r", stdin)
#define outt freopen("output.txt", "w", stdout)
#define all(arr) arr.begin(),arr.end()
ll power(ll x,ll y){ll res = 1;while(y){if(y&1) res = (res*x)%mod;y=y/2,x=(x*x)%mod;}return res%mod;}
vi tempp;

ll _mergeSort( ll temp[], ll left, ll right);
ll merge( ll temp[], ll left, ll mid, ll right);

/* This function sorts the input array and returns the
   number of inversions in the array */
ll mergeSort( ll array_size)
{
    ll* temp = (ll*)malloc(sizeof(ll) * array_size);
    return _mergeSort( temp, 0, array_size - 1);
}

/* An auxiliary recursive function that sorts the input array and
  returns the number of inversions in the array. */
ll _mergeSort( ll temp[], ll left, ll right)
{
    ll mid, inv_count = 0;
    if (right > left) {
        /* Divide the array llo two parts and call _mergeSortAndCountInv()
       for each of the parts */
        mid = (right + left) / 2;

        /* Inversion count will be sum of inversions in left-part, right-part
      and number of inversions in merging */
        inv_count = _mergeSort( temp, left, mid);
        inv_count += _mergeSort( temp, mid + 1, right);

        /*Merge the two parts*/
        inv_count += merge( temp, left, mid + 1, right);
    }
    return inv_count;
}

/* This funt merges two sorted arrays and returns inversion count in
   the arrays.*/
ll merge( ll temp[], ll left, ll mid, ll right)
{
    ll i, j, k;
    ll inv_count = 0;

    i = left; /* i is index for left subarray*/
    j = mid; /* j is index for right subarray*/
    k = left; /* k is index for resultant merged subarray*/
    while ((i <= mid - 1) && (j <= right)) {
        if (tempp[i] <= tempp[j]) {
            temp[k++] = tempp[i++];
        }
        else {
            temp[k++] = tempp[j++];

            /*this is tricky -- see above explanation/diagram for merge()*/
            inv_count = inv_count + (mid - i);
        }
    }

    /* Copy the remaining elements of left subtemppay
   (if there are any) to temp*/
    while (i <= mid - 1)
        temp[k++] = tempp[i++];

    /* Copy the remaining elements of right subtemppay
   (if there are any) to temp*/
    while (j <= right)
        temp[k++] = tempp[j++];

    /*Copy back the merged elements to original array*/
    for (i = left; i <= right; i++)
        tempp[i] = temp[i];

    return inv_count;
}
signed main()
{
    fast;
    ll n,i;
    set < ll > lol;
    cin>>n;
    ll ans = 0;
    ll arr[n+1];
    for(i=1;i<=n;i++){
        cin>>arr[i];
        if(arr[i]!=-1)
            lol.insert(arr[i]),tempp.pb(arr[i]);
    }
    vi useless;
    for(i=1;i<=n;i++){
        if(lol.find(i)==lol.end()){
            useless.pb(i);
        }
    }
    ll tot = useless.size();
    ans = (tot*(tot-1)%mod)*power(4,mod-2)%mod;
    ans+=mergeSort(tempp.size());
    ans%=mod;
    ll cnt = 0;
    ll pp = power(tot,mod-2);
    for(i=1;i<=n;i++)
    {
        if(arr[i]!=-1)
        {
            ll in = lower_bound(all(useless),arr[i])-useless.begin();
            ans+=((((tot-cnt)*in%mod)*pp)%mod);
            ans%=mod;
            ans+=((((tot-in)*(cnt)%mod)*pp)%mod);
            ans%=mod;
        }
        else
            cnt++;
    }
    cout<<ans;
}


#include <bits/stdc++.h>
using namespace std;
#define mod 998244353
#define pb push_back
#define mp make_pair
#define fi first
#define sec second
typedef long long  ll;
typedef long double  ld;
#define pii pair<ll,ll>
#define pic pair<ll,char>
#define vi vector< ll >
#define vvi vector< vi >
#define vpi vector< pii >
#define vvpi vector< vpi >
#define st  set <ll, greater <ll> >
#define mst  multiset <ll, greater <ll> >
#define fast ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define mapp  unordered_map <ll, ll>
#define ppii pair< pii, pii >
#define test(t) ll t;cin>>t;while(t--)
#define inarr(n) ll arr[n];for(ll i=0;i<n;i++)cin>>arr[i];
#define ingra(m) vvi arr(100005);for(ll i=0;i<m;i++){ll u,v;cin>>u>>v;arr[u].pb(v);arr[v].pb(u);}
#define mem(a,b) memset(a,b,sizeof(a))
#define inn freopen("input.txt", "r", stdin)
#define outt freopen("output.txt", "w", stdout)
#define all(arr) arr.begin(),arr.end()
ll power(ll x,ll y){ll res = 1;while(y){if(y&1) res = (res*x)%mod;y=y/2,x=(x*x)%mod;}return res%mod;}
vi tempp;

ll _mergeSort( ll temp[], ll left, ll right);
ll merge( ll temp[], ll left, ll mid, ll right);

/* This function sorts the input array and returns the
   number of inversions in the array */
ll mergeSort( ll array_size)
{
    ll* temp = (ll*)malloc(sizeof(ll) * array_size);
    return _mergeSort( temp, 0, array_size - 1);
}

/* An auxiliary recursive function that sorts the input array and
  returns the number of inversions in the array. */
ll _mergeSort( ll temp[], ll left, ll right)
{
    ll mid, inv_count = 0;
    if (right > left) {
        /* Divide the array llo two parts and call _mergeSortAndCountInv()
       for each of the parts */
        mid = (right + left) / 2;

        /* Inversion count will be sum of inversions in left-part, right-part
      and number of inversions in merging */
        inv_count = _mergeSort( temp, left, mid);
        inv_count += _mergeSort( temp, mid + 1, right);

        /*Merge the two parts*/
        inv_count += merge( temp, left, mid + 1, right);
    }
    return inv_count;
}

/* This funt merges two sorted arrays and returns inversion count in
   the arrays.*/
ll merge( ll temp[], ll left, ll mid, ll right)
{
    ll i, j, k;
    ll inv_count = 0;

    i = left; /* i is index for left subarray*/
    j = mid; /* j is index for right subarray*/
    k = left; /* k is index for resultant merged subarray*/
    while ((i <= mid - 1) && (j <= right)) {
        if (tempp[i] <= tempp[j]) {
            temp[k++] = tempp[i++];
        }
        else {
            temp[k++] = tempp[j++];

            /*this is tricky -- see above explanation/diagram for merge()*/
            inv_count = inv_count + (mid - i);
        }
    }

    /* Copy the remaining elements of left subtemppay
   (if there are any) to temp*/
    while (i <= mid - 1)
        temp[k++] = tempp[i++];

    /* Copy the remaining elements of right subtemppay
   (if there are any) to temp*/
    while (j <= right)
        temp[k++] = tempp[j++];

    /*Copy back the merged elements to original array*/
    for (i = left; i <= right; i++)
        tempp[i] = temp[i];

    return inv_count;
}
signed main()
{
    fast;
    ll n,i;
    set < ll > lol;
    cin>>n;
    ll ans = 0;
    ll arr[n+1];
    for(i=1;i<=n;i++){
        cin>>arr[i];
        if(arr[i]!=-1)
            lol.insert(arr[i]),tempp.pb(arr[i]);
    }
    vi useless;
    for(i=1;i<=n;i++)
    {
        if(lol.find(i)==lol.end())
        {
            useless.pb(i);
        }
    }
    ans = useless.size()*(useless.size()-1)*power(4,mod-2)%mod;
    ans+=mergeSort(tempp.size());
    ans%=mod;
    ll cnt = 0;
    for(i=1;i<=n;i++)
    {
        if(arr[i]!=-1)
        {
            ll in = upper_bound(all(useless),arr[i])-useless.begin();
            in = useless.size()-in;
            ll p = cnt*in*power(useless.size(),mod-2)%mod;
            p = p + (useless.size()-in)*(useless.size()-cnt)*power(useless.size(),mod-2)%mod;
            p%=mod;
            ans+=p;
            ans%=mod;
        }
        else
            cnt++;
    }
    cout<<ans;

}


#include <bits/stdc++.h>
using namespace std;
#define mod 998244353
#define pb push_back
#define mp make_pair
#define fi first
#define sec second
typedef long long  ll;
typedef long double  ld;
#define pii pair<ll,ll>
#define pic pair<ll,char>
#define vi vector< ll >
#define vvi vector< vi >
#define vpi vector< pii >
#define vvpi vector< vpi >
#define st  set <ll, greater <ll> >
#define mst  multiset <ll, greater <ll> >
#define fast ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define mapp  unordered_map <ll, ll>
#define ppii pair< pii, pii >
#define test(t) ll t;cin>>t;while(t--)
#define inarr(n) ll arr[n];for(ll i=0;i<n;i++)cin>>arr[i];
#define ingra(m) vvi arr(100005);for(ll i=0;i<m;i++){ll u,v;cin>>u>>v;arr[u].pb(v);arr[v].pb(u);}
#define mem(a,b) memset(a,b,sizeof(a))
#define inn freopen("input.txt", "r", stdin)
#define outt freopen("output.txt", "w", stdout)
#define all(arr) arr.begin(),arr.end()
ll power(ll x,ll y){ll res = 1;while(y){if(y&1) res = (res*x)%mod;y=y/2,x=(x*x)%mod;}return res%mod;}
vi temp;
ll getSum(ll BITree[], ll index)
{
    ll sum = 0; // Initialize result

    // Traverse ancestors of BITree[index]
    while (index > 0)
    {
        // Add current element of BITree to sum
        sum += BITree[index];

        // Move index to parent node in getSum View
        index -= index & (-index);
    }
    return sum;
}

// Updates a node in Binary Index Tree (BITree) at given index
// in BITree.  The given value 'val' is added to BITree[i] and
// all of its ancestors in tree.
void updateBIT(ll BITree[], ll n, ll index, ll val)
{
    // Traverse all ancestors and add 'val'
    while (index <= n)
    {
       // Add 'val' to current node of BI Tree
       BITree[index] += val;

       // Update index to that of parent in update View
       index += index & (-index);
    }
}

// Returns inversion count arr[0..n-1]
ll getInvCount(ll n)
{
    ll invcount = 0; // Initialize result

    // Find maximum element in arr[]
    ll maxElement = 0;
    for (ll i=0; i<n; i++)
        if (maxElement < temp[i])
            maxElement = temp[i];

    // Create a BIT with size equal to maxElement+1 (Extra
    // one is used so that elements can be directly be
    // used as index)
    ll BIT[maxElement+1];
    for (ll i=1; i<=maxElement; i++)
        BIT[i] = 0;

    // Traverse all elements from right.
    for (ll i=n-1; i>=0; i--)
    {
        // Get count of elements smaller than temp[i]
        invcount += getSum(BIT, temp[i]-1);

        // Add current element to BIT
        updateBIT(BIT, maxElement, temp[i], 1);
    }

    return invcount;
}
signed main()
{
    fast;
    ll n,i;
    set < ll > lol;
    cin>>n;
    ll ans = 0;
    ll arr[n+1];
    for(i=1;i<=n;i++){
        cin>>arr[i];
        if(arr[i]!=-1)
            lol.insert(arr[i]),temp.pb(arr[i]);
    }
    vi useless;
    for(i=1;i<=n;i++)
    {
        if(lol.find(i)==lol.end())
        {
            useless.pb(i);
        }
    }
    ans = (useless.size()*(useless.size()-1)%mod)*power(4,mod-2)%mod;
    ans+=getInvCount(temp.size());
    ans%=mod;
    ll cnt = 0;
    ll tot = useless.size();
    ll pp = power(tot,mod-2);
    for(i=1;i<=n;i++)
    {
        if(arr[i]!=-1)
        {
            ll in = lower_bound(all(useless),arr[i])-useless.begin();
            ans+=(tot-cnt)*in%mod*pp%mod;
            ans%=mod;
            ans+=(tot-in)*(cnt)%mod*pp%mod;
            ans%=mod;
        }
        else
            cnt++;
    }
    cout<<ans;
}


#include <bits/stdc++.h>
using namespace std;
#define mod 998244353
#define pb push_back
#define mp make_pair
#define fi first
#define sec second
typedef long long  ll;
typedef long double  ld;
#define pii pair<ll,ll>
#define pic pair<ll,char>
#define vi vector< ll >
#define vvi vector< vi >
#define vpi vector< pii >
#define vvpi vector< vpi >
#define st  set <ll, greater <ll> >
#define mst  multiset <ll, greater <ll> >
#define fast ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define mapp  unordered_map <ll, ll>
#define ppii pair< pii, pii >
#define test(t) ll t;cin>>t;while(t--)
#define inarr(n) ll arr[n];for(ll i=0;i<n;i++)cin>>arr[i];
#define ingra(m) vvi arr(100005);for(ll i=0;i<m;i++){ll u,v;cin>>u>>v;arr[u].pb(v);arr[v].pb(u);}
#define mem(a,b) memset(a,b,sizeof(a))
#define inn freopen("input.txt", "r", stdin)
#define outt freopen("output.txt", "w", stdout)
#define all(arr) arr.begin(),arr.end()
ll power(ll x,ll y){ll res = 1;while(y){if(y&1) res = (res*x)%mod;y=y/2,x=(x*x)%mod;}return res%mod;}
vi temp;
ll getSum(ll BITree[], ll index)
{
    ll sum = 0; // Initialize result

    // Traverse ancestors of BITree[index]
    while (index > 0)
    {
        // Add current element of BITree to sum
        sum += BITree[index];

        // Move index to parent node in getSum View
        index -= index & (-index);
    }
    return sum;
}

// Updates a node in Binary Index Tree (BITree) at given index
// in BITree.  The given value 'val' is added to BITree[i] and
// all of its ancestors in tree.
void updateBIT(ll BITree[], ll n, ll index, ll val)
{
    // Traverse all ancestors and add 'val'
    while (index <= n)
    {
       // Add 'val' to current node of BI Tree
       BITree[index] += val;

       // Update index to that of parent in update View
       index += index & (-index);
    }
}

// Returns inversion count arr[0..n-1]
ll getInvCount(ll n)
{
    ll invcount = 0; // Initialize result

    // Find maximum element in arr[]
    ll maxElement = 0;
    for (ll i=0; i<n; i++)
        if (maxElement < temp[i])
            maxElement = temp[i];

    // Create a BIT with size equal to maxElement+1 (Extra
    // one is used so that elements can be directly be
    // used as index)
    ll BIT[maxElement+1];
    for (ll i=1; i<=maxElement; i++)
        BIT[i] = 0;

    // Traverse all elements from right.
    for (ll i=n-1; i>=0; i--)
    {
        // Get count of elements smaller than temp[i]
        invcount += getSum(BIT, temp[i]-1);

        // Add current element to BIT
        updateBIT(BIT, maxElement, temp[i], 1);
    }

    return invcount;
}
signed main()
{
    fast;
    ll n,i;
    set < ll > lol;
    cin>>n;
    ll ans = 0;
    ll arr[n+1];
    for(i=1;i<=n;i++){
        cin>>arr[i];
        if(arr[i]!=-1)
            lol.insert(arr[i]),temp.pb(arr[i]);
    }
    vi useless;
    for(i=1;i<=n;i++)
    {
        if(lol.find(i)==lol.end())
        {
            useless.pb(i);
        }
    }
    ans = (useless.size()*(useless.size()-1)%mod)*power(4,mod-2)%mod;
    ans+=getInvCount(temp.size());
    ans%=mod;
    ll cnt = 0;
    ll tot = useless.size();
    ll pp = power(cnt,mod-2);
    for(i=1;i<=n;i++)
    {
        if(arr[i]!=-1)
        {
            ll in = lower_bound(all(useless),arr[i])-useless.begin();
            ans+=(tot-cnt)*in%mod*pp%mod;
            ans%=mod;
            ans+=(tot-in)*(cnt)%mod*pp%mod;
            ans%=mod;
        }
        else
            cnt++;
    }
    cout<<ans;
}


#include <bits/stdc++.h>
using namespace std;
#define mod 998244353
#define pb push_back
#define mp make_pair
#define fi first
#define sec second
typedef long long int  ll;
typedef long double  ld;
#define pii pair<ll,ll>
#define pic pair<ll,char>
#define vi vector< ll >
#define vvi vector< vi >
#define vpi vector< pii >
#define vvpi vector< vpi >
#define st  set <ll, greater <ll> >
#define mst  multiset <ll, greater <ll> >
#define fast ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define mapp  unordered_map <ll, ll>
#define ppii pair< pii, pii >
#define test(t) ll t;cin>>t;while(t--)
#define inarr(n) ll arr[n];for(ll i=0;i<n;i++)cin>>arr[i];
#define ingra(m) vvi arr(100005);for(ll i=0;i<m;i++){ll u,v;cin>>u>>v;arr[u].pb(v);arr[v].pb(u);}
#define mem(a,b) memset(a,b,sizeof(a))
#define inn freopen("input.txt", "r", stdin)
#define outt freopen("output.txt", "w", stdout)
#define all(arr) arr.begin(),arr.end()
ll power(ll x,ll y){ll res = 1;while(y){if(y&1) res = (res*x)%mod;y=y/2,x=(x*x)%mod;}return res%mod;}
vi temp;
int getSum(int BITree[], int index)
{
    int sum = 0; // Initialize result

    // Traverse ancestors of BITree[index]
    while (index > 0)
    {
        // Add current element of BITree to sum
        sum += BITree[index];

        // Move index to parent node in getSum View
        index -= index & (-index);
    }
    return sum;
}

// Updates a node in Binary Index Tree (BITree) at given index
// in BITree.  The given value 'val' is added to BITree[i] and
// all of its ancestors in tree.
void updateBIT(int BITree[], int n, int index, int val)
{
    // Traverse all ancestors and add 'val'
    while (index <= n)
    {
       // Add 'val' to current node of BI Tree
       BITree[index] += val;

       // Update index to that of parent in update View
       index += index & (-index);
    }
}

// Returns inversion count arr[0..n-1]
int getInvCount(int n)
{
    int invcount = 0; // Initialize result

    // Find maximum element in arr[]
    int maxElement = 0;
    for (int i=0; i<n; i++)
        if (maxElement < temp[i])
            maxElement = temp[i];

    // Create a BIT with size equal to maxElement+1 (Extra
    // one is used so that elements can be directly be
    // used as index)
    int BIT[maxElement+1];
    for (int i=1; i<=maxElement; i++)
        BIT[i] = 0;

    // Traverse all elements from right.
    for (int i=n-1; i>=0; i--)
    {
        // Get count of elements smaller than temp[i]
        invcount += getSum(BIT, temp[i]-1);

        // Add current element to BIT
        updateBIT(BIT, maxElement, temp[i], 1);
    }

    return invcount;
}
signed main()
{
    fast;
    ll n,i;
    set < ll > lol;
    cin>>n;
    ll ans = 0;
    ll arr[n+1];
    for(i=1;i<=n;i++){
        cin>>arr[i];
        if(arr[i]!=-1)
            lol.insert(arr[i]),temp.pb(arr[i]);
    }
    vi useless;
    for(i=1;i<=n;i++)
    {
        if(lol.find(i)==lol.end())
        {
            useless.pb(i);
        }
    }
    ans = useless.size()*(useless.size()-1)*power(4,mod-2)%mod;
    ans+=getInvCount(temp.size());
    ans%=mod;
    ll cnt = 0;
    for(i=1;i<=n;i++)
    {
        if(arr[i]!=-1)
        {
            ll in = upper_bound(all(useless),arr[i])-useless.begin();
            in = useless.size()-in;
            ll p = cnt*in*power(useless.size(),mod-2)%mod;
            p = p + (useless.size()-in)*(useless.size()-cnt)*power(useless.size(),mod-2)%mod;
            p%=mod;
            ans+=p;
            ans%=mod;
        }
        else
            cnt++;
    }
    cout<<ans;

}


#include <bits/stdc++.h>
using namespace std;
#define mod 998244353
#define pb push_back
#define mp make_pair
#define fi first
#define sec second
typedef long long  ll;
typedef long double  ld;
#define pii pair<ll,ll>
#define pic pair<ll,char>
#define vi vector< ll >
#define vvi vector< vi >
#define vpi vector< pii >
#define vvpi vector< vpi >
#define st  set <ll, greater <ll> >
#define mst  multiset <ll, greater <ll> >
#define fast ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define mapp  unordered_map <ll, ll>
#define ppii pair< pii, pii >
#define test(t) ll t;cin>>t;while(t--)
#define inarr(n) ll arr[n];for(ll i=0;i<n;i++)cin>>arr[i];
#define ingra(m) vvi arr(100005);for(ll i=0;i<m;i++){ll u,v;cin>>u>>v;arr[u].pb(v);arr[v].pb(u);}
#define mem(a,b) memset(a,b,sizeof(a))
#define inn freopen("input.txt", "r", stdin)
#define outt freopen("output.txt", "w", stdout)
#define all(arr) arr.begin(),arr.end()
ll power(ll x,ll y){ll res = 1;while(y){if(y&1) res = (res*x)%mod;y=y/2,x=(x*x)%mod;}return res%mod;}
vi temp;
ll getSum(ll BITree[], ll index)
{
    ll sum = 0; // Initialize result

    // Traverse ancestors of BITree[index]
    while (index > 0)
    {
        // Add current element of BITree to sum
        sum += BITree[index];

        // Move index to parent node in getSum View
        index -= index & (-index);
    }
    return sum;
}

// Updates a node in Binary Index Tree (BITree) at given index
// in BITree.  The given value 'val' is added to BITree[i] and
// all of its ancestors in tree.
void updateBIT(ll BITree[], ll n, ll index, ll val)
{
    // Traverse all ancestors and add 'val'
    while (index <= n)
    {
       // Add 'val' to current node of BI Tree
       BITree[index] += val;

       // Update index to that of parent in update View
       index += index & (-index);
    }
}

// Returns inversion count arr[0..n-1]
ll getInvCount(ll n)
{
    ll invcount = 0; // Initialize result

    // Find maximum element in arr[]
    ll maxElement = 0;
    for (ll i=0; i<n; i++)
        if (maxElement < temp[i])
            maxElement = temp[i];

    // Create a BIT with size equal to maxElement+1 (Extra
    // one is used so that elements can be directly be
    // used as index)
    ll BIT[maxElement+1];
    for (ll i=1; i<=maxElement; i++)
        BIT[i] = 0;

    // Traverse all elements from right.
    for (ll i=n-1; i>=0; i--)
    {
        // Get count of elements smaller than temp[i]
        invcount += getSum(BIT, temp[i]-1);

        // Add current element to BIT
        updateBIT(BIT, maxElement, temp[i], 1);
    }

    return invcount;
}
signed main()
{
    fast;
    ll n,i;
    set < ll > lol;
    cin>>n;
    ll ans = 0;
    ll arr[n+1];
    for(i=1;i<=n;i++){
        cin>>arr[i];
        if(arr[i]!=-1)
            lol.insert(arr[i]),temp.pb(arr[i]);
    }
    vi useless;
    for(i=1;i<=n;i++)
    {
        if(lol.find(i)==lol.end())
        {
            useless.pb(i);
        }
    }
    ans = useless.size()*(useless.size()-1)*power(4,mod-2)%mod;
    ans+=getInvCount(temp.size());
    ans%=mod;
    ll cnt = 0;
    for(i=1;i<=n;i++)
    {
        if(arr[i]!=-1)
        {
            ll in = lower_bound(all(useless),arr[i])-useless.begin();
            ll p = (useless.size()-cnt)*in%mod*power(useless.size(),mod-2)%mod;
            p = p + (useless.size()-in)*(cnt)%mod*power(useless.size(),mod-2)%mod;
            p%=mod;
            ans+=p;
            ans%=mod;
        }
        else
            cnt++;
    }
    cout<<ans;
}


#include <bits/stdc++.h>

#define ios ios_base::sync_with_stdio(false)
#define endl '\n'
#define max(a, b) ((a < b) ? b : a)
#define min(a, b) ((a< b) ? a : b)
#define int long long

using namespace std;

long long mod = 998244353;
vector<int> known;

vector<int> merge(vector<int> left, vector<int> right, int *inv_count) {
    vector<int> output;
    // multiple variable definition of the same type
    int i = 0, j = 0;

    // spaces around "<", after "while", before "{" for readability
    while (i < left.size() && j < right.size()) {

        // one-instruction trick again
        if (left[i] <= right[j])
            // i++ is evaluated to <previous value of i> and then increments i
            // this is strictly equivalent to your code, but shorter
            // check the difference with ++i
            output.push_back(left[i++]);
            // else because the two conditions were complementary
        else {
            output.push_back(right[j++]);
            // pointer incrementation
            *inv_count += (left.size() - i);
        }
    }

    // first field of for ommited because there is no need to initialize i
    for (; i < left.size(); i++)
        output.push_back(left[i]);

    for (; j < right.size(); j++)
        output.push_back(right[j]);

    return output;
}

vector<int> merge_sort(vector<int> input, int *inv_count) {
    // no-braces-idiom again
    // spaces around "<" and after "if" for readability
    if (input.size() < 2)
        return input;

    // no need for else keyword because of the return

    // multiple variable definition
    vector<int> left, right;

    int middle = input.size() / 2;

    // one-instruction for loop
    for (int i = 0; i < middle; i++)
        left.push_back(input[i]);

    for (int i = middle; i < input.size(); i++)
        right.push_back(input[i]);

    // no need for intermediate variable
    return merge(merge_sort(left, inv_count),
                 merge_sort(right, inv_count),
                 inv_count);
}

int gcd(int a, int b) {
    if (b == 0) {
        return a;
    } else {
        return gcd(b, a % b);
    }
}

int getInverse(int a) {
    int r[100];
    r[0] = a;
    for (int i = 1; i < 100; i++) {
        r[i] = (r[i - 1] * r[i - 1]) % mod;
    }

    int result = 1LL;
    int counter = 0;
    int m = mod - 2;
    while (m) {
        if (m & 1) {
            result = ((result * r[counter]) % mod);
        }
        m /= 2;
        counter++;
    }
    return result;
}

int32_t main() {
    ios;

    int n;
    cin >> n;
    int vals[n];
    bool came[n];
    memset(came, 0, sizeof(bool) * n);
    int unknowns = 0;
    for (int i = 0; i < n; i++) {
        cin >> vals[i];
        if (vals[i] != -1) {
            vals[i]--;
            known.push_back(vals[i]);
            came[vals[i]] = true;
        } else {
            unknowns++;
        }
    }

    int cc[n];
    memset(cc, 0, sizeof(int) * n);
    cc[0] = 1 - (came[0]);
    for (int i = 1; i < n; i++) {
        if (!came[i]) {
            cc[i] = cc[i - 1] + 1;
        } else {
            cc[i] = cc[i - 1];
        }
    }

    int inv_count = 0;

    merge_sort(known, &inv_count);

    inv_count %= mod;
    if (!unknowns) {

        cout << inv_count << endl;
        return 0;
    }

    int sumUp = 0;
    int counter = 0;
    for (int i = 0; i < n; i++) {
        if (vals[i] != -1) {
            sumUp += cc[vals[i]] * (unknowns - counter) + (unknowns - cc[vals[i]]) * (counter);
        } else {
            counter++;
        }
    }

    sumUp += unknowns * inv_count;
    sumUp = 4 * sumUp + (unknowns) * (unknowns - 1) * unknowns;

    int g = gcd(sumUp, 4 * unknowns);
    int sumDown = 4 * unknowns;

    sumUp = sumUp / g;
    sumDown /= g;

    int result = (sumUp * getInverse(sumDown)) % mod;

    if (result > mod)
        result = result % mod;

    cout << result << endl;

}


#include <bits/stdc++.h>

#define ios ios_base::sync_with_stdio(false)
#define endl '\n'
#define max(a, b) ((a < b) ? b : a)
#define min(a, b) ((a< b) ? a : b)
#define int long long

using namespace std;

long long mod = 998244353;
vector<int> known;

// void type -> does not return anything
void print(vector<int> input) {
    // range-based for loop (since C++ 11)
    // no brackets -> only one instruction in for loop
    for (int i : input)
        cout << i << ",";
}

vector<int> merge(vector<int> left, vector<int> right, int *inv_count) {
    vector<int> output;
    // multiple variable definition of the same type
    int i = 0, j = 0;

    // spaces around "<", after "while", before "{" for readability
    while (i < left.size() && j < right.size()) {

        // one-instruction trick again
        if (left[i] <= right[j])
            // i++ is evaluated to <previous value of i> and then increments i
            // this is strictly equivalent to your code, but shorter
            // check the difference with ++i
            output.push_back(left[i++]);
            // else because the two conditions were complementary
        else {
            output.push_back(right[j++]);
            // pointer incrementation
            *inv_count += (left.size() - i);
        }
    }

    // first field of for ommited because there is no need to initialize i
    for (; i < left.size(); i++)
        output.push_back(left[i]);

    for (; j < right.size(); j++)
        output.push_back(right[j]);

    return output;
}

vector<int> merge_sort(vector<int> input, int *inv_count) {
    // no-braces-idiom again
    // spaces around "<" and after "if" for readability
    if (input.size() < 2)
        return input;

    // no need for else keyword because of the return

    // multiple variable definition
    vector<int> left, right;

    int middle = input.size() / 2;

    // one-instruction for loop
    for (int i = 0; i < middle; i++)
        left.push_back(input[i]);

    for (int i = middle; i < input.size(); i++)
        right.push_back(input[i]);

    // no need for intermediate variable
    return merge(merge_sort(left, inv_count),
                 merge_sort(right, inv_count),
                 inv_count);
}

int gcd(int a, int b) {
    if (b == 0) {
        return a;
    } else {
        return gcd(b, a % b);
    }
}

int getInverse(int a) {
    int r[100];
    r[0] = a;
    for (int i = 1; i < 100; i++) {
        r[i] = (r[i - 1] * r[i - 1]) % mod;
    }

    int result = 1LL;
    int counter = 0;
    int m = mod - 2;
    while (m) {
        if (m & 1) {
            result = ((result * r[counter]) % mod);
        }
        m /= 2;
        counter++;
    }
    return result;
}

int32_t main() {
    ios;

    int n;
    cin >> n;
    int vals[n];
    bool came[n];
    memset(came, 0, sizeof(bool) * n);
    int unknowns = 0;
    for (int i = 0; i < n; i++) {
        cin >> vals[i];
        if (vals[i] != -1) {
            vals[i]--;
            known.push_back(vals[i]);
            came[vals[i]] = true;
        } else {
            unknowns++;
        }
    }

    int cc[n];
    memset(cc, 0, sizeof(int) * n);
    cc[0] = 1 - (came[0]);
    for (int i = 1; i < n; i++) {
        if (!came[i]) {
            cc[i] = cc[i - 1] + 1;
        } else {
            cc[i] = cc[i - 1];
        }
    }

    int inv_count = 0;

    merge_sort(known, &inv_count);

    if (!unknowns) {
        cout << inv_count << endl;
        return 0;
    }

    int sumUp = 0;
    int counter = 0;
    for (int i = 0; i < n; i++) {
        if (vals[i] != -1) {
            sumUp += cc[vals[i]] * (unknowns - counter) + (unknowns - cc[vals[i]]) * (counter);
        } else {
            counter++;
        }
    }

    sumUp += unknowns * inv_count;
    sumUp = 4 * sumUp + (unknowns) * (unknowns - 1) * unknowns;

    int g = gcd(sumUp, 4 * unknowns);
    int sumDown = 4 * unknowns;

    sumUp = sumUp / g;
    sumDown /= g;

    int result = (sumUp * getInverse(sumDown)) % mod;

    if (result > mod)
        result = result % mod;

    cout << result << endl;

}


#include <bits/stdc++.h>

#define ios ios_base::sync_with_stdio(false)
#define endl '\n'
#define max(a, b) ((a < b) ? b : a)
#define min(a, b) ((a< b) ? a : b)
#define int long long

using namespace std;

long long mod = 998244353;
vector<int> known;

vector<int> merge(vector<int> left, vector<int> right, int *inv_count) {
    vector<int> output;
    // multiple variable definition of the same type
    int i = 0, j = 0;

    // spaces around "<", after "while", before "{" for readability
    while (i < left.size() && j < right.size()) {

        // one-instruction trick again
        if (left[i] <= right[j])
            // i++ is evaluated to <previous value of i> and then increments i
            // this is strictly equivalent to your code, but shorter
            // check the difference with ++i
            output.push_back(left[i++]);
            // else because the two conditions were complementary
        else {
            output.push_back(right[j++]);
            // pointer incrementation
            *inv_count += (left.size() - i);
        }
    }

    // first field of for ommited because there is no need to initialize i
    for (; i < left.size(); i++)
        output.push_back(left[i]);

    for (; j < right.size(); j++)
        output.push_back(right[j]);

    return output;
}

vector<int> merge_sort(vector<int> input, int *inv_count) {
    // no-braces-idiom again
    // spaces around "<" and after "if" for readability
    if (input.size() < 2)
        return input;

    // no need for else keyword because of the return

    // multiple variable definition
    vector<int> left, right;

    int middle = input.size() / 2;

    // one-instruction for loop
    for (int i = 0; i < middle; i++)
        left.push_back(input[i]);

    for (int i = middle; i < input.size(); i++)
        right.push_back(input[i]);

    // no need for intermediate variable
    return merge(merge_sort(left, inv_count),
                 merge_sort(right, inv_count),
                 inv_count);
}

int gcd(int a, int b) {
    if (b == 0) {
        return a;
    } else {
        return gcd(b, a % b);
    }
}

int getInverse(int a) {
    int r[100];
    r[0] = a;
    for (int i = 1; i < 100; i++) {
        r[i] = (r[i - 1] * r[i - 1]) % mod;
    }

    int result = 1LL;
    int counter = 0;
    int m = mod - 2;
    while (m) {
        if (m & 1) {
            result = ((result * r[counter]) % mod);
        }
        m /= 2;
        counter++;
    }
    return result;
}

int32_t main() {
    ios;

    int n;
    cin >> n;
    int vals[n];
    bool came[n];
    memset(came, 0, sizeof(bool) * n);
    int unknowns = 0;
    for (int i = 0; i < n; i++) {
        cin >> vals[i];
        if (vals[i] != -1) {
            vals[i]--;
            known.push_back(vals[i]);
            came[vals[i]] = true;
        } else {
            unknowns++;
        }
    }

    int cc[n];
    memset(cc, 0, sizeof(int) * n);
    cc[0] = 1 - (came[0]);
    for (int i = 1; i < n; i++) {
        if (!came[i]) {
            cc[i] = cc[i - 1] + 1;
        } else {
            cc[i] = cc[i - 1];
        }
    }

    int inv_count = 0;

    merge_sort(known, &inv_count);

    inv_count %= mod;
    if (!unknowns) {

        cout << inv_count << endl;
        return 0;
    }

    int sumUp = 0;
    int counter = 0;
    for (int i = 0; i < n; i++) {
        if (vals[i] != -1) {
            sumUp += cc[vals[i]] * (unknowns - counter) + (unknowns - cc[vals[i]]) * (counter);
        } else {
            counter++;
        }
    }

    sumUp += unknowns * inv_count;
    sumUp = 4 * sumUp + (unknowns) * (unknowns - 1) * unknowns;

    int g = gcd(sumUp, 4 * unknowns);
    int sumDown = 4 * unknowns;

    sumUp = sumUp / g;
    sumDown /= g;

    sumUp %= mod;

    int result = (sumUp * getInverse(sumDown)) % mod;

    if (result > mod)
        result = result % mod;

    cout << result << endl;

}


#include <bits/stdc++.h>

#define ios ios_base::sync_with_stdio(false)
#define endl '\n'
#define max(a, b) ((a < b) ? b : a)
#define min(a, b) ((a< b) ? a : b)
#define int long long

using namespace std;

long long mod = 998244353;
vector<int> known;

// void type -> does not return anything
void print(vector<int> input) {
    // range-based for loop (since C++ 11)
    // no brackets -> only one instruction in for loop
    for (int i : input)
        cout << i << ",";
}

vector<int> merge(vector<int> left, vector<int> right, int *inv_count) {
    vector<int> output;
    // multiple variable definition of the same type
    int i = 0, j = 0;

    // spaces around "<", after "while", before "{" for readability
    while (i < left.size() && j < right.size()) {

        // one-instruction trick again
        if (left[i] <= right[j])
            // i++ is evaluated to <previous value of i> and then increments i
            // this is strictly equivalent to your code, but shorter
            // check the difference with ++i
            output.push_back(left[i++]);
            // else because the two conditions were complementary
        else {
            output.push_back(right[j++]);
            // pointer incrementation
            *inv_count += (left.size() - i);
        }
    }

    // first field of for ommited because there is no need to initialize i
    for (; i < left.size(); i++)
        output.push_back(left[i]);

    for (; j < right.size(); j++)
        output.push_back(right[j]);

    return output;
}

vector<int> merge_sort(vector<int> input, int *inv_count) {
    // no-braces-idiom again
    // spaces around "<" and after "if" for readability
    if (input.size() < 2)
        return input;

    // no need for else keyword because of the return

    // multiple variable definition
    vector<int> left, right;

    int middle = input.size() / 2;

    // one-instruction for loop
    for (int i = 0; i < middle; i++)
        left.push_back(input[i]);

    for (int i = middle; i < input.size(); i++)
        right.push_back(input[i]);

    // no need for intermediate variable
    return merge(merge_sort(left, inv_count),
                 merge_sort(right, inv_count),
                 inv_count);
}

int gcd(int a, int b) {
    if (b == 0) {
        return a;
    } else {
        return gcd(b, a % b);
    }
}

int getInverse(int a) {
    int r[100];
    r[0] = a;
    for (int i = 1; i < 100; i++) {
        r[i] = (r[i - 1] * r[i - 1]) % mod;
    }

    int result = 1LL;
    int counter = 0;
    int m = mod - 2;
    while (m) {
        if (m & 1) {
            result = ((result * r[counter]) % mod);
        }
        m /= 2;
        counter++;
    }
    return result;
}

int32_t main() {
    ios;

    int n;
    cin >> n;
    int vals[n];
    bool came[n];
    memset(came, 0, sizeof(bool) * n);
    int unknowns = 0;
    for (int i = 0; i < n; i++) {
        cin >> vals[i];
        if (vals[i] != -1) {
            vals[i]--;
            known.push_back(vals[i]);
            came[vals[i]] = true;
        } else {
            unknowns++;
        }
    }

    int cc[n];
    memset(cc, 0, sizeof(int) * n);
    cc[0] = 1 - (came[0]);
    for (int i = 1; i < n; i++) {
        if (!came[i]) {
            cc[i] = cc[i - 1] + 1;
        } else {
            cc[i] = cc[i - 1];
        }
    }

    int inv_count = 0;

    merge_sort(known, &inv_count);

    if (!unknowns) {
        cout << inv_count << endl;
        return 0;
    }

    int sumUp = 0;
    int counter = 0;
    for (int i = 0; i < n; i++) {
        if (vals[i] != -1) {
            sumUp += cc[vals[i]] * (unknowns - counter) + (unknowns - cc[vals[i]]) * (counter);
        } else {
            counter++;
        }
    }

    sumUp += unknowns * inv_count;
    sumUp = 4 * sumUp + (unknowns) * (unknowns - 1) * unknowns;

    int g = gcd(sumUp, 4 * unknowns);
    int sumDown = 4 * unknowns;

    sumUp = sumUp / g;
    sumDown /= g;

    int result = (sumUp * getInverse(sumDown)) % mod;

    cout << result << endl;

}


#include <bits/stdc++.h>

#define ios ios_base::sync_with_stdio(false)
#define endl '\n'
#define max(a, b) ((a < b) ? b : a)
#define min(a, b) ((a< b) ? a : b)
#define int long long

using namespace std;

long long mod = 998244353;
vector<int> known;

// void type -> does not return anything
void print(vector<int> input) {
    // range-based for loop (since C++ 11)
    // no brackets -> only one instruction in for loop
    for (int i : input)
        cout << i << ",";
}

vector<int> merge(vector<int> left, vector<int> right, int *inv_count) {
    vector<int> output;
    // multiple variable definition of the same type
    int i = 0, j = 0;

    // spaces around "<", after "while", before "{" for readability
    while (i < left.size() && j < right.size()) {

        // one-instruction trick again
        if (left[i] <= right[j])
            // i++ is evaluated to <previous value of i> and then increments i
            // this is strictly equivalent to your code, but shorter
            // check the difference with ++i
            output.push_back(left[i++]);
            // else because the two conditions were complementary
        else {
            output.push_back(right[j++]);
            // pointer incrementation
            *inv_count += (left.size() - i);
        }
    }

    // first field of for ommited because there is no need to initialize i
    for (; i < left.size(); i++)
        output.push_back(left[i]);

    for (; j < right.size(); j++)
        output.push_back(right[j]);

    return output;
}

vector<int> merge_sort(vector<int> input, int *inv_count) {
    // no-braces-idiom again
    // spaces around "<" and after "if" for readability
    if (input.size() < 2)
        return input;

    // no need for else keyword because of the return

    // multiple variable definition
    vector<int> left, right;

    int middle = input.size() / 2;

    // one-instruction for loop
    for (int i = 0; i < middle; i++)
        left.push_back(input[i]);

    for (int i = middle; i < input.size(); i++)
        right.push_back(input[i]);

    // no need for intermediate variable
    return merge(merge_sort(left, inv_count),
                 merge_sort(right, inv_count),
                 inv_count);
}

int gcd(int a, int b) {

    if (b == 0) {
        return a;
    } else {
        return gcd(b, a % b);
    }
}

int getInverse(int a) {
    int r[100];
    r[0] = a;
    for (int i = 1; i < 100; i++) {
        r[i] = (r[i - 1] * r[i - 1]) % mod;
    }

    int result = 1LL;
    int counter = 0;
    int m = mod - 2;
    while (m) {
        if (m & 1) {
            result = ((result * r[counter]) % mod);
        }
        m /= 2;
        counter++;
    }
    return result;
}

int32_t main() {
    ios;

    int n;
    cin >> n;
    int vals[n];
    bool came[n];
    memset(came, 0, sizeof(bool) * n);
    int unknowns = 0;
    for (int i = 0; i < n; i++) {
        cin >> vals[i];
        if (vals[i] != -1) {
            vals[i]--;
            known.push_back(vals[i]);
            came[vals[i]] = true;
        } else {
            unknowns++;
        }
    }

    int cc[n];
    memset(cc, 0, sizeof(int) * n);
    cc[0] = 1 - (came[0]);
    for (int i = 1; i < n; i++) {
        if (!came[i]) {
            cc[i] = cc[i - 1] + 1;
        } else {
            cc[i] = cc[i - 1];
        }
    }

    int inv_count = 0;

    merge_sort(known, &inv_count);

    if (!unknowns) {
        cout << inv_count << endl;
        return 0;
    }

    int sumUp = 0;
    int counter = 0;
    for (int i = 0; i < n; i++) {
        if (vals[i] != -1) {
            sumUp += cc[vals[i]] * (unknowns - counter) + (unknowns - cc[vals[i]]) * (counter);
        } else {
            counter++;
        }
    }

    sumUp += unknowns * inv_count;
    sumUp = 4 * sumUp + (unknowns) * (unknowns - 1) * unknowns;

    int g = gcd(sumUp, 4 * unknowns);
    int sumDown = 4 * unknowns;

    sumUp = sumUp / g;
    sumDown /= g;

    cout << (sumUp * getInverse(sumDown)) % mod << endl;

}