#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); atcoder::segtree usemin(n); for(int i = 0;i can(n); atcoder::segtree notuse(n); for(int i = 0;i ok(n, 0); atcoder::segtree conmax(n); atcoder::segtree ausemin(n); vector mcan(n); set ook; int ng = 0; auto judge = [&](int i) { // cout<<"j1"< i) { while(r-l>1){ int m = (r+l) / 2; if(pmax.prod(l, m) > i) r = m; else l = m; } mcan[i] = l; can.set(i, i); } ausemin.set(i, e2()); l = seg1.get(i).second.first; r = seg1.get(i).second.second; int pp = pmin.prod(l, r + 1); if(pp ans(n+1); int last = 0; vector,dat1>> rr; auto cut = [&](int i) { if(i==0) return; 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)); //erase(nl); dat1 newl = nnl; newl.second.second = i - 1; rr.push_back(make_pair(make_pair(nl, 1), seg1.get(nl))); newl.first = psum.prod(l, i).first; add(newl, nl); dat1 newi; newi.second.first = i; newi.second.second = r - 1; newi.first = psum.prod(i, r).first; rr.push_back(make_pair(make_pair(p[i], 1), seg1.get(p[i]))); add(newi, p[i]); }; ans[0] = seg1.all_prod().first.first; auto j2 = [&]() { while(true){ if(ng==n) return; if(use.find(ng)!=use.end()){ ng++; continue; } int ii = idx[ng]; auto itr = cutuse.lower_bound(ng); itr--; int ni = *itr; ni = p[ni]; if(ng<=ni){ ng++; continue; } return; } }; 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; } if(need==2) { //j2(); int aa = ausemin.all_prod(); aa = min(aa, n); auto itr = use.upper_bound(aa); int bb = can.all_prod(); bool fn = false; int wc; //cout<=mb) { fn = true; wc = p[mcan[bb]]; //cout<=n); // } if(fn) { //cout<>t; while(t--){ solve(); } }