题目大意:n个点排成一行,每个点有一个颜色C。问有多少
,使得
。
题解:考虑对序列分块,然后考虑计算ab不在同一块+a’b’不在同一块-ab不在同一块且a’b’不在同一块+ab在同一块且a’b’在同一块。最后一个还可以分为aba’b’在同一块和(ab和a’b’不在同一块)。所有东西通过优秀的实现都可以做到
。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define mod 1000000007
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
const int N=100010+10000,SZ=330,BC=455;//N/SZ+10;
int bc,sz,c[N],L[BC],R[BC],prec[BC][N],bel[N];
namespace prelude_space{
inline int prelude(int n)
{
sz=max(1,(int)sqrt(n/2+0.5)),bc=(n-1)/sz+1;
rep(i,1,bc)
{
L[i]=(i-1)*sz+1,R[i]=min(n,i*sz);
memcpy(prec[i],prec[i-1],sizeof(int)*(n+1));
rep(j,L[i],R[i]) bel[j]=i,prec[i][c[j]]++;
}
return 0;
}
}
inline int cntc(int x,int v) { return prec[x][v]-prec[x-1][v]; }
inline int sufc(int p,int v) { return prec[bc][v]-prec[p-1][v]; }
namespace solve00_space{
int Lc[N],Rc[N];
inline int solve(int *c)//[aba'b']
{
lint ans=0;
rep(i,1,bc)
{
rep(j,L[i],R[i])
{
rep(k,j+1,R[i]) Rc[c[k]]++;
rep(k,j+1,R[i]) Rc[c[k]]--,(c[j]!=c[k]?ans+=(lint)Lc[c[k]]*Rc[c[j]]:0);
Lc[c[j]]++;
}
rep(j,L[i],R[i]) Lc[c[j]]=0;
}
return int(ans%mod);
}
}
namespace solve0_space{
const int P=19999999,MXS=P+10,MXN=1e7+2e6;
struct umap{
int h[MXS],pre[MXN],val[MXN],cnt;lint y[MXN];
inline int count(lint v) { int p=int(v%P);for(int i=h[p];i;i=pre[i]) if(y[i]==v) return val[i];return 0; }
inline int inc(lint v)
{
int p=int(v%P);for(int i=h[p];i;i=pre[i]) if(y[i]==v) return ++val[i];
return val[++cnt]=1,y[cnt]=v,pre[cnt]=h[p],h[p]=cnt;
}
}pre;
inline lint hv(int a,int b) { return a*998244353ll+b; }
inline int solve(int *c)//[ab] [a'b']
{
lint ans=0;
rep(i,1,bc)
{
rep(j,L[i],R[i]) rep(k,j+1,R[i]) if(c[j]^c[k]) ans+=pre.count(hv(c[j],c[k]));
rep(j,L[i],R[i]) rep(k,j+1,R[i]) if(c[j]^c[k]) pre.inc(hv(c[j],c[k]));
}
return int(ans%mod);
}
}
namespace solve1_space{
int c2[N],c4[N],cnt[N];
inline int solve(int *c,int n)//[a][b..]
{
lint ans=0;
// rep(i,1,n) cerr<<c[i]sp;cerr ln;
rep(i,1,bc)
{
rep(j,L[i],R[i]) cnt[c[j]]++;
memset(c2,0,sizeof(int)*(n+1));
rep(j,R[i]+1,n) c4[c[j]]++;
lint tot=0,res=0;
rep(j,R[i]+1,n)
{
c4[c[j]]--,tot-=c2[c[j]];
res+=cnt[c[j]]*(tot-(lint)c2[c[j]]*c4[c[j]]);
c2[c[j]]++,tot+=c4[c[j]];
}
rep(j,L[i],R[i]) cnt[c[j]]=0;
ans+=res%mod;
}
return ans%=mod,ans+=mod,ans%=mod,int(ans);
}
}
namespace solve2_space{
inline int solve(int *c)//[a][ba'][b']
{
lint ans=0;
rep(i,1,bc) rep(j,L[i],R[i]) rep(k,j+1,R[i]) if(c[j]^c[k])
ans+=(lint)prec[i-1][c[k]]*sufc(i+1,c[j]);
return int(ans%mod);
}
}
namespace solve3_space{
int cnt[N];
inline int solve(int *c)//[a][b][a'][b']
{
lint ans=0;
rep(i,1,bc) rep(j,i+1,bc)
{
lint tot=0,res=0;
rep(a,L[j],R[j]) if(prec[i-1][c[a]]&&!cnt[c[a]])
cnt[c[a]]=cntc(j,c[a])*prec[i-1][c[a]],tot+=cnt[c[a]];
tot%=mod;
rep(b,L[i],R[i]) res+=sufc(j+1,c[b])*(tot-cnt[c[b]]);
ans+=res%mod;
rep(a,L[j],R[j]) cnt[c[a]]=0;
}
return ans%=mod,ans+=mod,ans%=mod,int(ans);
}
}
int main()
{
// freopen("data.in","r",stdin);
int n=inn();lint ans=0;rep(i,1,n) c[i]=inn();
prelude_space::prelude(n);
ans+=solve0_space::solve(c);//[ab][a'b']
ans+=solve00_space::solve(c);//[aba'b']
R[bc]=bc*sz;
ans+=solve1_space::solve(c,R[bc]);reverse(c+1,c+R[bc]+1);//[a][b...]
ans+=solve1_space::solve(c,R[bc]);reverse(c+1,c+R[bc]+1);
R[bc]=n;
ans-=solve2_space::solve(c);//[a][ba'][b']
ans-=solve3_space::solve(c);//[a][b][a'][b']
ans%=mod,ans+=mod,ans%=mod;return !printf("%lld\n",ans);
}