QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#298899 | #7899. Say Hello to the Future | ucup-team087# | RE | 0ms | 3556kb | C++20 | 25.8kb | 2024-01-06 15:43:37 | 2024-01-06 15:43:39 |
Judging History
answer
#ifndef LOCAL
#pragma GCC optimize ("Ofast")
#pragma GCC optimize ("unroll-loops")
#endif
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
//#define int ll
#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif
template<class t,class u> bool chmax(t&a,u b){if(a<b){a=b;return true;}else return false;}
template<class t,class u> bool chmin(t&a,u b){if(b<a){a=b;return true;}else return false;}
template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;
using pi=pair<int,int>;
using vi=vc<int>;
template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
return os<<"{"<<p.a<<","<<p.b<<"}";
}
template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
os<<"{";
for(auto e:v)os<<e<<",";
return os<<"}";
}
#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
os<<t<<" ";
dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif
using uint=unsigned;
using ull=unsigned long long;
template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
return os<<vc<t>(all(a));
}
template<int i,class T>
void print_tuple(ostream&,const T&){
}
template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
if(i)os<<",";
os<<get<i>(t);
print_tuple<i+1,T,Args...>(os,t);
}
template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
os<<"{";
print_tuple<0,tuple<Args...>,Args...>(os,t);
return os<<"}";
}
ll read(){
ll i;
cin>>i;
return i;
}
vi readvi(int n,int off=0){
vi v(n);
rep(i,n)v[i]=read()+off;
return v;
}
pi readpi(int off=0){
int a,b;cin>>a>>b;
return pi(a+off,b+off);
}
template<class t>
void print_single(t x,int suc=1){
cout<<x;
if(suc==1)
cout<<"\n";
if(suc==2)
cout<<" ";
}
template<class t,class u>
void print_single(const pair<t,u>&p,int suc=1){
print_single(p.a,2);
print_single(p.b,suc);
}
template<class T>
void print_single(const vector<T>&v,int suc=1){
rep(i,v.size())
print_single(v[i],i==int(v.size())-1?suc:2);
}
template<class T>
void print_offset(const vector<T>&v,ll off,int suc=1){
rep(i,v.size())
print_single(v[i]+off,i==int(v.size())-1?suc:2);
}
template<class T,size_t N>
void print_single(const array<T,N>&v,int suc=1){
rep(i,N)
print_single(v[i],i==int(N)-1?suc:2);
}
template<class T>
void print(const T&t){
print_single(t);
}
template<class T,class ...Args>
void print(const T&t,const Args&...args){
print_single(t,2);
print(args...);
}
string readString(){
string s;
cin>>s;
return s;
}
template<class T>
T sq(const T& t){
return t*t;
}
void YES(bool ex=true){
cout<<"YES\n";
if(ex)exit(0);
#ifdef LOCAL
cout.flush();
#endif
}
void NO(bool ex=true){
cout<<"NO\n";
if(ex)exit(0);
#ifdef LOCAL
cout.flush();
#endif
}
void Yes(bool ex=true){
cout<<"Yes\n";
if(ex)exit(0);
#ifdef LOCAL
cout.flush();
#endif
}
void No(bool ex=true){
cout<<"No\n";
if(ex)exit(0);
#ifdef LOCAL
cout.flush();
#endif
}
//#define CAPITAL
/*
void yes(bool ex=true){
#ifdef CAPITAL
cout<<"YES"<<"\n";
#else
cout<<"Yes"<<"\n";
#endif
if(ex)exit(0);
#ifdef LOCAL
cout.flush();
#endif
}
void no(bool ex=true){
#ifdef CAPITAL
cout<<"NO"<<"\n";
#else
cout<<"No"<<"\n";
#endif
if(ex)exit(0);
#ifdef LOCAL
cout.flush();
#endif
}*/
void possible(bool ex=true){
#ifdef CAPITAL
cout<<"POSSIBLE"<<"\n";
#else
cout<<"Possible"<<"\n";
#endif
if(ex)exit(0);
#ifdef LOCAL
cout.flush();
#endif
}
void impossible(bool ex=true){
#ifdef CAPITAL
cout<<"IMPOSSIBLE"<<"\n";
#else
cout<<"Impossible"<<"\n";
#endif
if(ex)exit(0);
#ifdef LOCAL
cout.flush();
#endif
}
constexpr ll ten(int n){
return n==0?1:ten(n-1)*10;
}
const ll infLL=LLONG_MAX/3;
#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif
int topbit(signed t){
return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
return t==0?-1:63-__builtin_clzll(t);
}
int topbit(ull t){
return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
return a==0?64:__builtin_ctzll(a);
}
int botbit(ull a){
return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
return __builtin_popcount(t);
}
int popcount(ll t){
return __builtin_popcountll(t);
}
int popcount(ull t){
return __builtin_popcountll(t);
}
int bitparity(ll t){
return __builtin_parityll(t);
}
bool ispow2(int i){
return i&&(i&-i)==i;
}
ll mask(int i){
return (ll(1)<<i)-1;
}
ull umask(int i){
return (ull(1)<<i)-1;
}
ll minp2(ll n){
if(n<=1)return 1;
else return ll(1)<<(topbit(n-1)+1);
}
bool inc(int a,int b,int c){
return a<=b&&b<=c;
}
template<class t> void mkuni(vc<t>&v){
sort(all(v));
v.erase(unique(all(v)),v.ed);
}
ll rand_int(ll l, ll r) { //[l, r]
//#ifdef LOCAL
static mt19937_64 gen;
/*#else
static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
#endif*/
return uniform_int_distribution<ll>(l, r)(gen);
}
ll rand_int(ll k){ //[0,k)
return rand_int(0,k-1);
}
template<class t>
void myshuffle(vc<t>&a){
rep(i,si(a))swap(a[i],a[rand_int(0,i)]);
}
template<class t,class u>
int lwb(const vc<t>&v,const u&a){
return lower_bound(all(v),a)-v.bg;
}
template<class t,class u>
bool bis(const vc<t>&v,const u&a){
return binary_search(all(v),a);
}
vvc<int> readGraph(int n,int m){
vvc<int> g(n);
rep(i,m){
int a,b;
cin>>a>>b;
//sc.read(a,b);
a--;b--;
g[a].pb(b);
g[b].pb(a);
}
return g;
}
vvc<int> readTree(int n){
return readGraph(n,n-1);
}
template<class t>
vc<t> presum(const vc<t>&a){
vc<t> s(si(a)+1);
rep(i,si(a))s[i+1]=s[i]+a[i];
return s;
}
vc<ll> presum(const vi&a){
vc<ll> s(si(a)+1);
rep(i,si(a))s[i+1]=s[i]+a[i];
return s;
}
//BIT で数列を管理するときに使う (CF850C)
template<class t>
vc<t> predif(vc<t> a){
gnr(i,1,si(a))a[i]-=a[i-1];
return a;
}
template<class t>
vvc<ll> imos(const vvc<t>&a){
int n=si(a),m=si(a[0]);
vvc<ll> b(n+1,vc<ll>(m+1));
rep(i,n)rep(j,m)
b[i+1][j+1]=b[i+1][j]+b[i][j+1]-b[i][j]+a[i][j];
return b;
}
//verify してないや
void transvvc(int&n,int&m){
swap(n,m);
}
template<class t,class... Args>
void transvvc(int&n,int&m,vvc<t>&a,Args&...args){
assert(si(a)==n);
vvc<t> b(m,vi(n));
rep(i,n){
assert(si(a[i])==m);
rep(j,m)b[j][i]=a[i][j];
}
a.swap(b);
transvvc(n,m,args...);
}
//CF854E
void rotvvc(int&n,int&m){
swap(n,m);
}
template<class t,class... Args>
void rotvvc(int&n,int&m,vvc<t>&a,Args&...args){
assert(si(a)==n);
vvc<t> b(m,vi(n));
rep(i,n){
assert(si(a[i])==m);
rep(j,m)b[m-1-j][i]=a[i][j];
}
a.swap(b);
rotvvc(n,m,args...);
}
//ソートして i 番目が idx[i]
//CF850C
template<class t>
vi sortidx(const vc<t>&a){
int n=si(a);
vi idx(n);iota(all(idx),0);
sort(all(idx),[&](int i,int j){return a[i]<a[j];});
return idx;
}
//vs[i]=a[idx[i]]
//例えば sortidx で得た idx を使えば単にソート列になって返ってくる
//CF850C
template<class t>
vc<t> a_idx(const vc<t>&a,const vi&idx){
int n=si(a);
assert(si(idx)==n);
vc<t> vs(n);
rep(i,n)vs[i]=a[idx[i]];
return vs;
}
//CF850C
vi invperm(const vi&p){
int n=si(p);
vi q(n);
rep(i,n)q[p[i]]=i;
return q;
}
template<class t,class s=t>
s SUM(const vc<t>&a){
return accumulate(all(a),s(0));
}
template<class t,size_t K,class s=t>
s SUM(const array<t,K>&a){
return accumulate(all(a),s(0));
}
template<class t>
t MAX(const vc<t>&a){
return *max_element(all(a));
}
template<class t>
pair<t,int> MAXi(const vc<t>&a){
auto itr=max_element(all(a));
return mp(*itr,itr-a.bg);
}
template<class A>
auto MIN(const A&a){
return *min_element(all(a));
}
template<class t>
pair<t,int> MINi(const vc<t>&a){
auto itr=min_element(all(a));
return mp(*itr,itr-a.bg);
}
vi vid(int n){
vi res(n);iota(all(res),0);
return res;
}
template<class S>
void soin(S&s){
sort(all(s));
}
template<class S,class F>
void soin(S&s,F&&f){
sort(all(s),forward<F>(f));
}
template<class S>
S soout(S s){
soin(s);
return s;
}
template<class S>
void rein(S&s){
reverse(all(s));
}
template<class S>
S reout(S s){
rein(s);
return s;
}
template<class t,class u>
pair<t,u>&operator+=(pair<t,u>&a,pair<t,u> b){
a.a+=b.a;a.b+=b.b;return a;}
template<class t,class u>
pair<t,u>&operator-=(pair<t,u>&a,pair<t,u> b){
a.a-=b.a;a.b-=b.b;return a;}
template<class t,class u>
pair<t,u> operator+(pair<t,u> a,pair<t,u> b){return mp(a.a+b.a,a.b+b.b);}
template<class t,class u>
pair<t,u> operator-(pair<t,u> a,pair<t,u> b){return mp(a.a-b.a,a.b-b.b);}
template<class t,class u>
pair<t,u> operator-(pair<t,u> a){return mp(-a.a,-a.b);}
template<class t,class u>
istream&operator>>(istream&is,pair<t,u>&a){
return is>>a.a>>a.b;
}
template<class t>
t gpp(vc<t>&vs){
assert(si(vs));
t res=move(vs.back());
vs.pop_back();
return res;
}
template<class t,class u>
void pb(vc<t>&a,const vc<u>&b){
a.insert(a.ed,all(b));
}
template<class t,class...Args>
vc<t> cat(vc<t> a,Args&&...b){
(pb(a,forward<Args>(b)),...);
return a;
}
template<class t,class u>
vc<t>& operator+=(vc<t>&a,u x){
for(auto&v:a)v+=x;
return a;
}
template<class t,class u>
vc<t> operator+(vc<t> a,u x){
return a+=x;
}
template<class t>
vc<t> operator+(const vc<t>&a,const vc<t>&b){
vc<t> c(max(si(a),si(b)));
rep(i,si(a))c[i]+=a[i];
rep(i,si(b))c[i]+=b[i];
return c;
}
template<class t,class u>
vc<t>& operator-=(vc<t>&a,u x){
for(auto&v:a)v-=x;
return a;
}
template<class t,class u>
vc<t>& operator-(vc<t> a,u x){
return a-=x;
}
template<class t,class u>
void remval(vc<t>&a,const u&v){
a.erase(remove(all(a),v),a.ed);
}
//消した要素の個数を返してくれる
//UCUP 2-8-F
template<class t,class F>
int remif(vc<t>&a,F f){
auto itr=remove_if(all(a),f);
int res=a.ed-itr;
a.erase(itr,a.ed);
return res;
}
template<class VS,class u>
void fila(VS&vs,const u&a){
fill(all(vs),a);
}
template<class t,class u>
int findid(const vc<t>&vs,const u&a){
auto itr=find(all(vs),a);
if(itr==vs.ed)return -1;
else return itr-vs.bg;
}
template<class t>
void rtt(vc<t>&vs,int i){
rotate(vs.bg,vs.bg+i,vs.ed);
}
//N() が単位元
//VERIFY: yosupo
//CF407E
template<class N>
struct segtree{
vc<N> x;
int n,s;
segtree(){}
template<class t>
segtree(const vc<t>&a){
n=a.size();
s=1;
while(s<n){s*=2;}
x.resize(s*2);
rep(i,n)
x[s+i]=N(a[i]);
gnr(i,1,s)
x[i]=N::merge(x[i*2],x[i*2+1]);
}
//NOT Verified
segtree(int nn){
resize(nn);
}
void resize(int nn){
n=nn;
s=1;
while(s<n){s*=2;}
x.assign(s*2,N());
gnr(i,1,s)
x[i]=N::merge(x[i*2],x[i*2+1]);
}
template<class t>
void load(const vc<t>&a){
n=a.size();
s=1;
while(s<n){s*=2;}
x.resize(s*2);
rep(i,n)
x[s+i]=N(a[i]);
rng(i,n,s)
x[s+i]=N();
gnr(i,1,s)
x[i]=N::merge(x[i*2],x[i*2+1]);
}
void clear(){
rep(i,n)
x[s+i]=N();
gnr(i,1,s)
x[i]=N::merge(x[i*2],x[i*2+1]);
}
N point_get(int i){
assert(inc(0,i,n-1));
return x[i+s];
}
void point_set(int i,const N&t){
assert(inc(0,i,n-1));
i+=s;
x[i]=t;
while(i>>=1)x[i]=N::merge(x[i*2],x[i*2+1]);
}
void point_merge(int i,const N&t){
assert(inc(0,i,n-1));
i+=s;
x[i]=N::merge(x[i],t);
while(i>>=1)x[i]=N::merge(x[i*2],x[i*2+1]);
}
template<class F,class...Args>
void point_change(int i,F f,Args&&...args){
assert(inc(0,i,n-1));
i+=s;
(x[i].*f)(forward<Args>(args)...);
while(i>>=1)x[i]=N::merge(x[i*2],x[i*2+1]);
}
N composite(int b,int e){
assert(0<=b&&b<=e&&e<=n);
N lf,rt;
for(int l=b+s,r=e+s;l<r;l>>=1,r>>=1){
if (l&1){
lf=N::merge(lf,x[l]);
l++;
}
if (r&1){
r--;
rt=N::merge(x[r],rt);
}
}
return N::merge(lf,rt);
}
N getall(){
return x[1];
}
//UTPC2020E
//n 超えるかもしれない
template <class F,class... Args>
pair<int,N> max_right(int l,F f,Args&&... args){
assert((N().*f)(forward<Args>(args)...));
assert(0<=l&&l<=n);
if(l==n)return mp(n,N());
l+=s;
N sm;
assert((sm.*f)(forward<Args>(args)...));
do {
while (l % 2 == 0) l >>= 1;
if (!(N::merge(sm,x[l]).*f)(forward<Args>(args)...)){
while (l < s) {
l = (2 * l);
N tmp=N::merge(sm,x[l]);
if ((tmp.*f)(forward<Args>(args)...)) {
sm = tmp;
l++;
}
}
return mp(l - s,sm);
}
sm = N::merge(sm, x[l]);
l++;
} while ((l & -l) != l);
return mp(n,sm);
}
//UTPC2020E
template <class F,class... Args>
pair<int,N> min_left(int r,F f,Args&&... args){
assert((N().*f)(forward<Args>(args)...));
assert(0<=r&&r<=n);
if(r==0)return mp(0,N());
r+=s;
N sm;
do {
r--;
while (r > 1 && (r % 2)) r >>= 1;
if (!(N::merge(x[r],sm).*f)(forward<Args>(args)...)) {
while (r < s) {
r = (2 * r + 1);
N tmp=N::merge(x[r],sm);
if ((tmp.*f)(forward<Args>(args)...)) {
sm = tmp;
r--;
}
}
return mp(r + 1 - s,sm);
}
sm = N::merge(x[r], sm);
} while ((r & -r) != r);
return mp(0,sm);
}
//行列とか乗せて必要なのはベクトルとの積,みたいなときに使える?
//CF Goodbye 2016 E
//CF 896 F
template<class F,class T,class... Args>
T accumulate(int l,int r,F f,T t,Args&&... args) {
assert(0<=l&&l<=r&&r<=n);
static int buf[2][30];
int cnt[2]{};
for(l+=s,r+=s;l<r;l>>=1,r>>=1){
if(l&1)buf[0][cnt[0]++]=l;
if(r&1)buf[1][cnt[1]++]=r-1;
l++;
}
rep(i,cnt[0])t=(x[buf[0][i]].*f)(t,forward<Args>(args)...);
per(i,cnt[1])t=(x[buf[1][i]].*f)(t,forward<Args>(args)...);
return t;
}
};
//atcoder-library をまあまあコピーして使っている
//N() が単位元
//merge で片方が inactive のときはもう片方をそのまま返す,
//といったときに,lazy の情報までコピーして渡さないようにする
//クエリできる点が[0,s)だったのを[0,n)に変えた (UCUP1-21D)
//ch,max_rightは動くと思う
//ちゃんと test してないから assert とかが壊れたらごめん
//VERIFY:
//https://atcoder.jp/contests/practice2/tasks/practice2_k
template<class N,bool Beats=false>
struct seglazy{
vc<N> x;
int n,L,s;
seglazy(){}
template<class T>
seglazy(const vc<T>& a){
n=a.size();
L=0;
while((1<<L)<n)L++;
s=1<<L;
x.resize(s*2);
rep(i,n)x[s+i]=N(a[i]);
gnr(i,1,s)upd(i);
}
seglazy(int nn){
n=nn;
L=0;
while((1<<L)<n)L++;
s=1<<L;
x.assign(s*2,N());
gnr(i,1,s)upd(i);
}
void upd(int i){
x[i]=N::merge(x[i*2],x[i*2+1]);
}
void push(int i){
x[i].push(x[i*2],x[i*2+1]);
}
N composite(int l,int r){
assert(0<=l&&l<=r&&r<=n);
if(l==r)return N();
l+=s;
r+=s;
for (int i = L; i >= 1; i--) {
if (((l >> i) << i) != l) push(l >> i);
if (((r >> i) << i) != r) push((r - 1) >> i);
}
N sml,smr;
while (l < r) {
if (l & 1) sml = N::merge(sml, x[l++]);
if (r & 1) smr = N::merge(x[--r], smr);
l >>= 1;
r >>= 1;
}
return N::merge(sml, smr);
}
//UCUP1-21 D
template<class F,class... Args>
void ch_beats(int i,F f,Args&&... args){
if((x[i].*f)(forward<Args>(args)...))return;
push(i);
ch_beats(i*2,f,forward<Args>(args)...);
ch_beats(i*2+1,f,forward<Args>(args)...);
upd(i);
}
template<class F,class... Args>
void ch(int l, int r, F f,Args&&... args) {
assert(0<=l&&l<=r&&r<=n);
if (l == r) return;
l+=s;
r+=s;
for (int i = L; i >= 1; i--) {
if (((l >> i) << i) != l) push(l >> i);
if (((r >> i) << i) != r) push((r - 1) >> i);
}
static int buf[2][30];
int cnt[2]{};
{
int l2 = l, r2 = r;
while (l < r) {
if (l & 1){
//(x[l++].*f)(forward<Args>(args)...);
buf[0][cnt[0]++]=l++;
}
if (r & 1){
//(x[--r].*f)(forward<Args>(args)...);
buf[1][cnt[1]++]=--r;
}
l >>= 1;
r >>= 1;
}
l = l2;
r = r2;
}
if constexpr(Beats){
rep(i,cnt[0])ch_beats(buf[0][i],f,forward<Args>(args)...);
per(i,cnt[1])ch_beats(buf[1][i],f,forward<Args>(args)...);
}else{
rep(i,cnt[0])(x[buf[0][i]].*f)(forward<Args>(args)...);
per(i,cnt[1])(x[buf[1][i]].*f)(forward<Args>(args)...);
}
for (int i = 1; i <= L; i++) {
if (((l >> i) << i) != l) upd(l >> i);
if (((r >> i) << i) != r) upd((r - 1) >> i);
}
}
template<class F,class... Args>
void chall(F f,Args&&... args){
if constexpr(Beats){
ch_beats(1,f,forward<Args>(args)...);
}else{
(x[1].*f)(forward<Args>(args)...);
}
}
N getall(){return x[1];}
template <class F,class... Args>
pair<int,N> max_right(int l,F f,Args&&... args){
assert(0<=l&&l<=n);
if(l==n)return mp(n,N());
l+=s;
for (int i = L; i >= 1; i--) push(l >> i);
N sm;
assert((sm.*f)(forward<Args>(args)...));
do {
while (l % 2 == 0) l >>= 1;
if (!(N::merge(sm,x[l]).*f)(forward<Args>(args)...)){
while (l < s) {
push(l);
l = (2 * l);
N tmp=N::merge(sm,x[l]);
if ((tmp.*f)(forward<Args>(args)...)) {
sm = tmp;
l++;
}
}
return mp(l - s,sm);
}
sm = N::merge(sm, x[l]);
l++;
} while ((l & -l) != l);
return mp(n,sm);
}
//XXI Opencup Krakow M
template <class F,class... Args>
pair<int,N> min_left(int r,F f,Args&&... args){
assert(0<=r&&r<=n);
if(r==0)return mp(0,N());
r+=s;
for (int i = L; i >= 1; i--) push((r - 1) >> i);
N sm;
do {
r--;
while (r > 1 && (r % 2)) r >>= 1;
if (!(N::merge(x[r],sm).*f)(forward<Args>(args)...)) {
while (r < s) {
push(r);
r = (2 * r + 1);
N tmp=N::merge(x[r],sm);
if ((tmp.*f)(forward<Args>(args)...)) {
sm = tmp;
r--;
}
}
return mp(r + 1 - s,sm);
}
sm = N::merge(x[r], sm);
} while ((r & -r) != r);
return mp(0,sm);
}
template<class F,class...Args>
void point_change(int p,F f,Args&&...args){
assert(0 <= p && p < n);
p += s;
for (int i = L; i >= 1; i--) push(p >> i);
(x[p].*f)(forward<Args>(args)...);
for (int i = 1; i <= L; i++) upd(p >> i);
}
void point_merge(int p,const N&t){
assert(0 <= p && p < n);
p += s;
for (int i = L; i >= 1; i--) push(p >> i);
x[p]=N::merge(x[p],t);
for (int i = 1; i <= L; i++) upd(p >> i);
}
N point_get(int p){
assert(0 <= p && p < n);
p += s;
for (int i = L; i >= 1; i--) push(p >> i);
return x[p];
}
void point_set(int p,N val){
assert(0 <= p && p < n);
p += s;
for (int i = L; i >= 1; i--) push(p >> i);
x[p]=val;
for (int i = 1; i <= L; i++) upd(p >> i);
}
void enumerater(int l,int r,int i,int b,int e,vc<N>&dst){
if(e<=l||r<=b)
return;
if(l+1==r){
dst.pb(x[i]);
return;
}
push(i);
int m=(l+r)/2;
enumerater(l,m,i*2,b,e,dst);
enumerater(m,r,i*2+1,b,e,dst);
}
void enumerate(int b,int e,vc<N>&dst){
assert(0<=b&&b<=e&&e<=n);
return enumerater(0,s,1,b,e,dst);
}
};
//mint107 は verify してねえ
//#define DYNAMIC_MOD
struct modinfo{uint mod,root;
#ifdef DYNAMIC_MOD
constexpr modinfo(uint m,uint r):mod(m),root(r),im(0){set_mod(m);}
ull im;
constexpr void set_mod(uint m){
mod=m;
im=ull(-1)/m+1;
}
uint product(uint a,uint b)const{
ull z=ull(a)*b;
uint x=((unsigned __int128)z*im)>>64;
uint v=uint(z)-x*mod;
return v<mod?v:v+mod;
}
#endif
};
template<modinfo const&ref>
struct modular{
static constexpr uint const &mod=ref.mod;
static modular root(){return modular(ref.root);}
uint v;
//modular(initializer_list<uint>ls):v(*ls.bg){}
modular(ll vv=0){s(vv%mod+mod);}
modular& s(uint vv){
v=vv<mod?vv:vv-mod;
return *this;
}
modular operator-()const{return modular()-*this;}
modular& operator+=(const modular&rhs){return s(v+rhs.v);}
modular&operator-=(const modular&rhs){return s(v+mod-rhs.v);}
modular&operator*=(const modular&rhs){
#ifndef DYNAMIC_MOD
v=ull(v)*rhs.v%mod;
#else
v=ref.product(v,rhs.v);
#endif
return *this;
}
modular&operator/=(const modular&rhs){return *this*=rhs.inv();}
modular operator+(const modular&rhs)const{return modular(*this)+=rhs;}
modular operator-(const modular&rhs)const{return modular(*this)-=rhs;}
modular operator*(const modular&rhs)const{return modular(*this)*=rhs;}
modular operator/(const modular&rhs)const{return modular(*this)/=rhs;}
modular pow(ll n)const{
if(n<0)return inv().pow(-n);
modular res(1),x(*this);
while(n){
if(n&1)res*=x;
x*=x;
n>>=1;
}
return res;
}
modular inv()const{return pow(mod-2);}
/*modular inv()const{
int x,y;
int g=extgcd<ll>(v,mod,x,y);
assert(g==1);
if(x<0)x+=mod;
return modular(x);
}*/
friend modular operator+(ll x,const modular&y){
return modular(x)+y;
}
friend modular operator-(ll x,const modular&y){
return modular(x)-y;
}
friend modular operator*(ll x,const modular&y){
return modular(x)*y;
}
friend modular operator/(ll x,const modular&y){
return modular(x)/y;
}
friend ostream& operator<<(ostream&os,const modular&m){
return os<<m.v;
}
friend istream& operator>>(istream&is,modular&m){
ll x;is>>x;
m=modular(x);
return is;
}
bool operator<(const modular&r)const{return v<r.v;}
bool operator==(const modular&r)const{return v==r.v;}
bool operator!=(const modular&r)const{return v!=r.v;}
explicit operator bool()const{
return v;
}
};
#ifndef DYNAMIC_MOD
extern constexpr modinfo base{998244353,3};
//extern constexpr modinfo base{1000000007,0};
//extern constexpr modinfo base{2147483579,0};//2^31 未満の最大の安全素数
//modinfo base{1,0};
#ifdef USE_GOOD_MOD
static_assert(base.mod==998244353);
#endif
#else
modinfo base(1,0);
extern constexpr modinfo base107(1000000007,0);
using mint107=modular<base107>;
#endif
using mint=modular<base>;
mint parity(int i){
return i%2==0?1:-1;
}
//Range add,sum
struct N{
int len;
mint sum,lz;
N():len(0),sum(0),lz(0){}
N(int LEN,mint val):len(LEN),sum(val),lz(0){}
void add(mint v){
sum+=v*len;
lz+=v;
return;
}
void push(N&x,N&y){
x.add(lz);
y.add(lz);
lz=0;
}
static N merge(N x,N y){
return N(x.len+y.len,x.sum+y.sum);
}
};
struct MaxNode{
pi v;
MaxNode(pi vv=pi(-inf,-1)):v(vv){}
static MaxNode merge(const MaxNode&a,const MaxNode&b){
return MaxNode(max(a.v,b.v));
}
bool ok(pi z){
return v<z;
}
};
bool dbg=false;
vc<mint> calc(vc<pi> ai){
int n=si(ai);
segtree<MaxNode> seg(ai);
vc<N> ini(n+1,N(1,0));
ini[0].sum=1;
seglazy<N> dp(ini);
rep(i,n){
int l=seg.min_left(i,&MaxNode::ok,ai[i]).a;
int r=seg.max_right(i+1,&MaxNode::ok,ai[i]).a;
if((i-l)<(r-i-1)){
rng(j,l,i+1){
int kmin=max(j+ai[i].a,i+1);
int kmax=r;
mint val=dp.point_get(j).sum;
dp.ch(kmin,kmax+1,&N::add,val);
}
}else{
rng(k,i+1,r+1){
int jmin=l;
int jmax=min(k-ai[i].a,i);
mint val=dp.composite(jmin,jmax+1).sum;
dp.point_change(k,&N::add,val);
}
}
}
vc<mint> res(n+1);
rep(i,n+1)res[i]=dp.point_get(i).sum;
return res;
}
void slv(){
int n;cin>>n;
vi a=readvi(n);
vc<pi> ai(n);
rep(i,n)ai[i]=pi(a[i],i);
vc<mint> dp[2];
rep(step,2){
dp[step]=calc(ai);
rein(ai);
}
rein(dp[1]);
vc<mint> ans(n,dp[0][n]);
rep(i,n)ans[i]+=dp[0][i]*dp[1][i+1];
dmp(dp[0]);
dmp(dp[1]);
dmp(ans);
rep(step,2){
vc<mint> sum[2];
rep(k,2)sum[k]=presum(dp[k]);
segtree<MaxNode> seg(ai);
auto eval=[&](int jmin,int jmax,int kmin,int kmax,int w){
assert(jmin<=jmax);
assert(kmin<=kmax);
mint res=0;
if(jmax-jmin<kmax-kmin){
rng(j,jmin,jmax+1){
int l=max(kmin,j+w);
int r=kmax;
if(l<=r){
res+=dp[0][j]*(sum[1][r+1]-sum[1][l]);
}
}
}else{
rng(k,kmin,kmax+1){
int l=jmin;
int r=min(jmax,k-w);
if(l<=r){
res+=(sum[0][r+1]-sum[0][l])*dp[1][k];
}
}
}
return res;
};
vi pos;
rep(i,n){
if(step==0){
int jmin=seg.min_left(i,&MaxNode::ok,ai[i]).a;
int jmax=i;
int kmin=i+1;
int kmax=seg.max_right(i+1,&MaxNode::ok,ai[i]).a;
ans[(step==0?i:n-1-i)]-=eval(jmin,jmax,kmin,kmax,ai[i].a);
}
auto work=[&](int x){
int jmin=seg.min_left(x,&MaxNode::ok,ai[x]).a;
int jmax=x;
int kmin=i+1;
int kmax=seg.max_right(i+1,&MaxNode::ok,ai[x]).a;
ans[(step==0?i:n-1-i)]+=eval(jmin,jmax,kmin,kmax,ai[x].a);
};
while(si(pos)&&ai[pos.back()]<ai[i]){
work(gpp(pos));
}
pos.pb(i);
}
rein(ai);
rep(k,2)rein(dp[k]);
swap(dp[0],dp[1]);
dmp(ans);
}
print(ans);
}
signed main(){
cin.tie(0);
ios::sync_with_stdio(0);
cout<<fixed<<setprecision(20);
if(dbg){
while(1)slv();
}else{
//int t;cin>>t;rep(_,t)
slv();
}
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3556kb
input:
5 1 3 2 1 2
output:
3 6 3 3 6
result:
ok 5 tokens
Test #2:
score: -100
Runtime Error
input:
200000 15922 15391 11782 4758 1973 19909 16800 6438 3821 986 18599 2011 338 19886 12401 4169 11143 12665 3230 12565 15065 15056 5090 16908 13677 12634 11435 1425 8647 3876 10694 12256 3853 19901 5723 11065 6147 13613 13768 15794 14993 5819 8117 13871 14708 15099 7152 9810 14438 10557 3209 1265 13915...