QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#298701 | #7901. Basic Substring Structure | ucup-team087# | WA | 56ms | 3552kb | C++20 | 16.3kb | 2024-01-06 14:09:30 | 2024-01-06 14:09:31 |
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);
}
bool dbg=false;
//O(N+max(A)) なので座標圧縮してから動かしてください
//Verify yosupo (N=500000,string,43ms)
template<class t>vi sais(t a){
int n=si(a),m=*max_element(all(a))+1;
vi pos(m+1),x(m),sa(n),val(n),lms;
for(auto c:a)pos[c+1]++;
rep(i,m)pos[i+1]+=pos[i];
vc<bool> s(n);
per(i,n-1)s[i]=a[i]!=a[i+1]?a[i]<a[i+1]:s[i+1];
auto ind=[&](const vi&ls){
fill(all(sa),-1);
auto L=[&](int i){if(i>=0&&!s[i])sa[x[a[i]]++]=i;};
auto S=[&](int i){if(i>=0&& s[i])sa[--x[a[i]]]=i;};
rep(i,m)x[i]=pos[i+1];
per(i,si(ls))S(ls[i]);
rep(i,m)x[i]=pos[i];
L(n-1);
rep(i,n)L(sa[i]-1);
rep(i,m)x[i]=pos[i+1];
per(i,n)S(sa[i]-1);
};
auto ok=[&](int i){return i==n||(!s[i-1]&&s[i]);};
auto same=[&](int i,int j){
do{
if(a[i++]!=a[j++])return false;
}while(!ok(i)&&!ok(j));
return ok(i)&&ok(j);
};
rng(i,1,n)if(ok(i))lms.pb(i);
ind(lms);
if(si(lms)){
int p=-1,w=0;
for(auto v:sa)if(v&&ok(v)){
if(p!=-1&&same(p,v))w--;
val[p=v]=w++;
}
vi b=lms;
for(auto&v:b)v=val[v];
b=sais(b);
for(auto&v:b)v=lms[v];
ind(b);
}
return sa;
}
struct SA{
int n;
vi sa,as,lcp;
template<class t> SA(t s):n(si(s)),as(n),lcp(n-1){
{//座標圧縮,値域が小さいなら skip 可
auto vs=s;mkuni(vs);
for(auto&v:s)v=lwb(vs,v);
}
sa=sais(s);
//as
rep(i,n)as[sa[i]]=i;
//lcp
int w=0;
for(auto i:as){
if(w)w--;
if(i<n-1){
while(max(sa[i],sa[i+1])+w<n&&s[sa[i]+w]==s[sa[i+1]+w]) w++;
lcp[i]=w;
}
}
}
};
//VERIFY: yosupo
//AOJGRL5C
template<class t,class u>
struct sparsetable{
vvc<t> a;
u f;
const t id;
sparsetable(const vc<t>& d,u ff,t w):f(ff),id(w){
if(d.empty())return;
int n=d.size(),h=topbit(n);
a.resize(h+1);
a[0]=d;
rng(j,1,h+1){
a[j].resize(n-(1<<j)+1);
rep(i,n-(1<<j)+1)
a[j][i]=f(a[j-1][i],a[j-1][i+(1<<(j-1))]);
}
}
t get(int b,int e){
assert(b<=e);
if(b==e)return id;
int d=topbit(e-b);
return f(a[d][b],a[d][e-(1<<d)]);
}
};
const auto imin=[](int a,int b){
return min(a,b);
};
using minst=sparsetable<int,decltype(imin)>;
//Xmas2012B
template<class S>
struct string_cmp{
S s;
int n;
SA sa;
minst t;
string_cmp(const S&ss):s(ss),n(si(s)),sa(s),t(sa.lcp,imin,inf){}
int getlcp(int i,int j){
if(i==n||j==n)return 0;
if(i==j)return n-i;
i=sa.as[i];
j=sa.as[j];
if(i>j)swap(i,j);
return t.get(i,j);
}
int cmpchar(int i,int j){
assert(0<=i&&i<n);
assert(0<=j&&j<n);
assert(s[i]!=s[j]);
return s[i]<s[j]?-1:1;
}
//[a,b)<[c,d)-> -1
//same -> 0
//[a,b)>[c,d) -> 1
int cmp(int a,int b,int c,int d){
int len=min({getlcp(a,c),b-a,d-c});
if(a+len==b&&c+len==d)return 0;
if(a+len==b)return -1;
if(c+len==d)return 1;
return cmpchar(a+len,c+len);
}
//ABC240H
int cmp(pi a,pi b){
return cmp(a.a,a.b,b.a,b.b);
}
int cmp_samelen(int a,int b,int len){
return cmp(a,a+len,b,b+len);
}
//[l,r] のリストを受け取り,それらを連結してできる文字列の比較をする
//リストの長さ 2 の場合は verify (Xmas2012 B)
int cmp_list(vc<pi> a,vc<pi> b){
int i=0,j=0;
while(1){
while(i<si(a)&&a[i].a==a[i].b)i++;
while(j<si(b)&&b[j].a==b[j].b)j++;
if(i==si(a)&&j==si(b))return 0;
if(i==si(a))return -1;
if(j==si(b))return 1;
int k=min(a[i].b-a[i].a,b[j].b-b[j].a);
int x=cmp_samelen(a[i].a,b[j].a,k);
if(x)return x;
a[i].a+=k;
b[j].a+=k;
}
assert(0);
}
//[l,r] のリストを受け取り,それらを連結してできる文字列の LCP を求める
//UCUP 2-17-H
int lcp_list(vc<pi> a,vc<pi> b){
int i=0,j=0,res=0;
while(1){
while(i<si(a)&&a[i].a==a[i].b)i++;
while(j<si(b)&&b[j].a==b[j].b)j++;
if(i==si(a)||j==si(b))return res;
int k=min(a[i].b-a[i].a,b[j].b-b[j].a);
int x=getlcp(a[i].a,b[j].a);
if(x<k)return res+x;
res+=k;
a[i].a+=k;
b[j].a+=k;
}
assert(0);
}
};
void slv(){
int n;cin>>n;
vi s=readvi(n,-1);
rep(i,n)s.pb(i);
string_cmp<vi> z(s);
vi w(n);
rep(i,n)
w[i]=min(z.getlcp(0,i),n-i);
dmp(w);
int base=SUM(w);
vvc<int> buf(n);
rng(i,1,n){
if(i+w[i]<n){
buf[w[i]].pb(i);
buf[i+w[i]].pb(i);
}
}
vi ma(n+1),mb(n+1);
auto add=[&](int l,int r,int v){
//(-1)x+b=v
//-l+b=v
//dmp2(l,r,v);
ma[l]+=-1;
ma[r]-=-1;
mb[l]+=l+v;
mb[r]-=l+v;
};
rng(i,1,n){
add(i,i+w[i],w[i]);
add(0,min(w[i],i),w[i]);
}
rep(i,n){
ma[i+1]+=ma[i];
mb[i+1]+=mb[i];
}
//dmp(ma);
//dmp(mb);
vi ans(n,base);
rep(i,n){
dmp(i);
int mx=0;
map<int,vi> ls;
for(auto j:buf[i]){
if(w[j]==i){
ls[s[j+w[j]]].pb(j);
}else if(j+w[j]==i){
ls[s[w[j]]].pb(j);
}else assert(false);
}
for(auto [c,js]:ls){
int dif=0;
for(auto j:js){
dif-=w[j];
vc<pi> a;
a.eb(0,i);
a.eb(n+c,n+c+1);
a.eb(i+1,n);
vc<pi> b;
if(j<i)b.eb(j,i);
if(j<i+1)b.eb(n+c,n+c+1);
b.eb(max(i+1,j),n);
dmp2(a,b,z.lcp_list(a,b));
dif+=z.lcp_list(a,b);
}
dmp2(c,js,dif);
chmax(mx,dif);
}
dmp2(ma[i]*i+mb[i]);
ans[i]+=mx-(ma[i]*i+mb[i]);
}
dmp(ans);
int val=0;
rep(i,n){
val+=ans[i]^(i+1);
}
print(val);
}
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: 1ms
memory: 3480kb
input:
2 4 2 1 1 2 12 1 1 4 5 1 4 1 9 1 9 8 10
output:
15 217
result:
ok 2 lines
Test #2:
score: -100
Wrong Answer
time: 56ms
memory: 3552kb
input:
10000 8 2 1 2 1 1 1 2 2 9 2 2 1 2 1 2 1 2 1 15 2 1 2 1 1 1 1 2 2 1 2 1 2 2 1 2 1 1 10 2 1 1 1 2 2 1 1 2 2 3 2 1 2 11 1 2 2 1 1 2 1 2 2 1 1 14 2 1 1 1 1 2 1 1 1 2 2 1 2 1 12 2 2 2 1 2 2 2 1 1 2 1 2 4 2 1 1 2 8 1 2 2 2 1 2 1 1 8 1 1 2 1 2 1 1 1 6 2 1 1 1 2 2 14 2 2 1 1 1 1 2 2 2 1 2 2 1 1 10 1 2 2 1 1...
output:
94 127 347 3 211 9 265 363 279 15 95 113 58 351 225 3 334 357 376 316 3 19 123 66 15 82 36 258 11 63 28 85 84 103 251 190 21 48 303 63 102 20 24 67 311 362 266 296 348 281 326 281 231 312 3 330 54 328 3 69 32 147 322 39 329 90 241 3 164 345 250 20 155 3 404 393 390 81 269 359 20 54 21 279 3 17 351 3...
result:
wrong answer 2nd lines differ - expected: '128', found: '127'