#include #include #include using namespace std; using ll = long long; #include #include #include #include using mint = atcoder::modint998244353; using dat1 = pair,pair>; dat1 op1(dat1 a,dat1 b) { dat1 now; now.first.first = a.first.first * b.first.second + b.first.first; now.first.second = a.first.second * b.first.second; return now; } dat1 e1(){ return make_pair(make_pair(0, 1), make_pair(-1, -1)); } using dat2 = int; dat2 op2(dat2 a,dat2 b) { return min(a,b); } dat2 e2() { return 1e9; } using dat3 = int; dat3 op3(dat3 a,dat3 b){ return max(a,b); } dat3 e3(){ return -1; } int fuse = 0; int f1(dat3 a) { return a < fuse; } void solve(){ int n; cin>>n; vector p(n); for(int i = 0;i>p[i]; for(int i = 0;i idx(n); for(int i = 0;i seg1(n); // 数字の index set use; // 場所の index set cutuse; atcoder::segtree pmin(p); atcoder::segtree pmax(p); atcoder::segtree psum(n); atcoder::segtree usemax(n); for(int i = 0;i can(n); atcoder::segtree notuse(n); for(int i = 0;i ok(n, 0); atcoder::segtree conmax(n); auto judge = [&](int i) { // cout<i) can.set(i, i); }; auto add = [&](dat1 now,int i) { use.insert(i); notuse.set(i, e2()); cutuse.insert(now.second.first); usemax.set(idx[i], idx[i]); ok[i] = 1; seg1.set(i, now); conmax.set(i, pmax.prod(now.second.first, now.second.second+1)); judge(i); auto itr = use.upper_bound(i); if(itr!=use.end()) { int ni = *itr; can.set(ni,e2()); judge(ni); } }; auto erase = [&](int i) { auto ee = seg1.get(i); use.erase(i); notuse.set(i, i); cutuse.erase(ee.second.first); ok[i] = 0; conmax.set(i, e3()); seg1.set(i, e1()); usemax.set(idx[i], e3()); can.set(i, e2()); auto itr = use.upper_bound(i); if(itr!=use.end()) { int ni = *itr; can.set(ni, e2()); judge(ni); } }; for(int i = 0;i ans(n+1); int last = 0; vector,dat1>> rr; auto cut = [&](int i) { assert(i!=0); auto itr = cutuse.lower_bound(i); int r = n; if(itr!=cutuse.end()) r = *itr; assert(itr!=cutuse.begin()); itr--; int l = *itr; int nl = p[l]; dat1 nnl = seg1.get(nl); rr.push_back(make_pair(make_pair(nl, 0), nnl)); dat1 newl = nnl; newl.second.second = i - 1; newl.first = psum.prod(l, i).first; add(newl, nl); rr.push_back(make_pair(make_pair(nl, 1), newl)); dat1 newi; newi.second.first = i; newi.second.second = r - 1; newi.first = psum.prod(i, r).first; add(newi, p[i]); rr.push_back(make_pair(make_pair(p[i], 1), newi)); }; ans[0] = seg1.all_prod().first.first; for(int t = 1;t < n;) { mint tmp = 0; if(last==n){ ans[t] = seg1.all_prod().first.first; t++; continue; } { int ni = idx[last]; int nj = ni - 1; if(0<=nj && p[nj] == last - 1) { cut(ni); } } // assert(last!=n-1); int ni = last + 1; int need = 0; rr.clear(); int pos = n; if(last-1>=0) pos = idx[last-1] + 1; if(pos!=n && cutuse.find(pos) == cutuse.end()) need++; if(cutuse.find(idx[last])==cutuse.end()) need++; if(need==0){ last++; continue; } // cout<1){ int m = (r+l)/2; if(pmin.prod(l, r) > mc) r = m; else l = m; } cut(r-1); }else{ int ni = idx[mn]; cut(ni); } tmp = seg1.all_prod().first.first; reverse(rr.begin(),rr.end()); for(auto e:rr){ if(e.first.second==1) erase(e.first.first); else add(e.second, e.first.first); } } // cout<>t; while(t--){ solve(); } }