反射弧(arcs) - 分块 - 哈希表

题目大意:n个点排成一行,每个点有一个颜色C。问有多少 a &lt; b &lt; a ′ &lt; b ′ a&lt;b&lt;a&#x27;&lt;b&#x27; a<b<a<b,使得 C a = C a ′ , C b = C b ′ , C a ! = C b C_a=C_{a&#x27;},C_b=C_{b&#x27;},C_a!=C_b Ca=Ca,Cb=Cb,Ca!=Cb n ≤ 1 0 5 n\le10^5 n105
题解:考虑对序列分块,然后考虑计算ab不在同一块+a’b’不在同一块-ab不在同一块且a’b’不在同一块+ab在同一块且a’b’在同一块。最后一个还可以分为aba’b’在同一块和(ab和a’b’不在同一块)。所有东西通过优秀的实现都可以做到 O ( n n ) O\left(n\sqrt n\right) O(nn )

#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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值