[cf718E]Matvey's Birthday

考虑$i$到$j$的最短路,记作$dis(i,j)$,令字符集大小为$T=8$,有$dis(i,j)<2T$

证明:

记$l=dis(i,j)$,假设这条最短路依次经过$a_{0},a_{1},...,a_{l}$(其中$a_{0}=i,a_{l}=j$)

若存在$0le i<j<kle l$,满足$s_{a_{i}}=s_{a_{j}}=s_{a_{k}}$,显然此时直接从$a_{i}$到$a_{k}$更短

即每一种字符最多出现两次,根据抽屉原理,即有$l<2T$

更进一步的,对其分两类讨论:

1.没有使用第2类边,那么显然是$|i-j|$

2.使用了第2类边,假设是这条边是$(a,b)$,则$dis(i,j)=min_{(a,b)}dis(i,a)+dis(b,j)+1$

考虑先枚举$s_{a}=s_{b}=c$,此时不难发现$a$和$b$独立,即可以对$a$和$b$分别取$dis(i,a)$和$dis(b,j)$最小

更具体的,记$f_{i,c}=min_{s_{j}=c}dis(i,j)$,即$dis(i,j)=min_{c}f_{i,c}+f_{j,c}+1$

综上,即
$$
dis(i,j)=min(|i-j|,min_{c}f_{i,c}+f_{j,c}+1)
$$
关于如何计算$f_{i,c}$,枚举$c$并从该种字符的位置出发进行bfs,第2类边显然仅允许第一次搜到该颜色时走,因此单次复杂度为$(n)$,总复杂度为$o(nT)$

此时,考虑暴力从大到小枚举直径$din [1,2T)$,并求出最短路大于等于$d$的点对数,若不为0则此时的$d$以及求出的点对数即为答案

考虑如何求最短路大于等于$d$的点对数,即$|i-j|ge d$且$min_{c}f_{i,c}+f_{j,c}+1ge d$的$(i,j)$对数

先考虑第二个条件,即$min_{c}f_{i,c}+f_{j,c}+1ge d$

构造$g_{c_{1},c_{2}}=min_{s_{i}=c_{1}}f_{i,c_{2}}$,显然可以$o(nT)$计算,同时有以下性质:$g_{s_{i},c}le f_{i,c}le g_{s_{i},c}+1$

左半部分是根据$g_{c_{1},c_{2}}$的定义,在求$min$时取$i$即可

右半部分考虑$f_{i,c}$第一次直接从$i$开始走第2类边,即为$g_{s_{i},c}+1$

由此,将$f_{i,c}-g_{s_{i},c}$看作二进制上的某一位,即压成了一个$2^{T}$的二进制数

对于每一个$i$,令这个二进制数为$state_{i}$,则通过$(s_{i},state_{i})$即可确定所有$f_{i,c}$,进而也可以确定判定结果,那么不妨去枚举$(s_{i},state_{i})$,再预处理其数量即可

统计出每一个状态的数量,并对每两个状态都求出$min_{c}f_{i,c}+f_{j,c}+1$(因为$d$会变化),由于预处理时$d$不变化,$d$变化时通过预处理可以$o(1)$,复杂度为$o(nT+T^{3}2^{2T})$($o(nT)$是统计数量)

再对第一个条件容斥,即减去$min_{c}f_{i,c}+f_{j,c}+1ge d$且$|i-j|<d$的$(i,j)$对数

直接$o(nT)$枚举$i$和$j$,通过前面的预处理可以$o(1)$判定前者,复杂度为$o(nT^{2})$(对每一个$d$都要做一次)

将两者的答案累加即可,最终总复杂度为$o(nT^{2}+T^{3}2^{2T})$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 #define T 8
 5 #define L 15
 6 queue<int>q;
 7 vector<int>v[T];
 8 int n,a[N],vis[N],visc[T],f[N][T],g[T][T],state[N],tot[T][1<<T],d[T][1<<T][T][1<<T];
 9 char s[N];
10 int main(){
11     scanf("%d%s",&n,s+1);
12     for(int i=1;i<=n;i++)a[i]=s[i]-'a';
13     for(int i=1;i<=n;i++)v[a[i]].push_back(i);
14     for(int i=0;i<T;i++){
15         if (!v[i].size()){
16             for(int j=1;j<=n;j++)f[j][i]=0x3f3f3f3f;
17             continue;
18         }
19         memset(vis,0,sizeof(vis));
20         memset(visc,0,sizeof(visc));
21         for(int j=0;j<v[i].size();j++){
22             q.push(v[i][j]);
23             vis[v[i][j]]=1;
24         }
25         while (!q.empty()){
26             int k=q.front();
27             q.pop();
28             if ((k>1)&&(!vis[k-1])){
29                 f[k-1][i]=f[k][i]+1;
30                 q.push(k-1);
31                 vis[k-1]=1;
32             }
33             if ((k<n)&&(!vis[k+1])){
34                 f[k+1][i]=f[k][i]+1;
35                 q.push(k+1);
36                 vis[k+1]=1;
37             }
38             if (!visc[a[k]]){
39                 for(int j=0;j<v[a[k]].size();j++)
40                     if (!vis[v[a[k]][j]]){
41                         f[v[a[k]][j]][i]=f[k][i]+1;
42                         q.push(v[a[k]][j]);
43                         vis[v[a[k]][j]]=1;
44                     }
45                 visc[a[k]]=1;
46             }
47         }
48     }
49     memset(g,0x3f,sizeof(g));
50     for(int i=0;i<T;i++)
51         for(int j=0;j<T;j++)
52             for(int k=0;k<v[j].size();k++)g[j][i]=min(g[j][i],f[v[j][k]][i]);
53     for(int i=1;i<=n;i++){
54         for(int j=T-1;j>=0;j--)state[i]=(state[i]<<1)+(f[i][j]-g[a[i]][j]);
55         tot[a[i]][state[i]]++;
56     }
57     for(int i1=0;i1<T;i1++)
58         for(int j1=0;j1<(1<<T);j1++)
59             for(int i2=0;i2<T;i2++)
60                 for(int j2=0;j2<(1<<T);j2++){
61                     d[i1][j1][i2][j2]=0x3f3f3f3f;
62                     for(int i=0;i<T;i++){
63                         int x=g[i1][i]+((j1&(1<<i))>0),y=g[i2][i]+((j2&(1<<i))>0);
64                         d[i1][j1][i2][j2]=min(d[i1][j1][i2][j2],x+y+1);
65                     }
66                 }
67     for(int i=L;i;i--){
68         long long ans=0;
69         for(int i1=0;i1<T;i1++)
70             for(int j1=0;j1<(1<<T);j1++)
71                 for(int i2=0;i2<T;i2++)
72                     for(int j2=0;j2<(1<<T);j2++)
73                         if (d[i1][j1][i2][j2]>=i)ans+=1LL*tot[i1][j1]*tot[i2][j2];
74         for(int j=1;j<=n;j++)
75             for(int k=max(j-i+1,1);k<=min(j+i-1,n);k++)
76                 if (d[a[j]][state[j]][a[k]][state[k]]>=i)ans--;
77         if (ans){
78             printf("%d %lld",i,ans/2);
79             return 0;
80         }
81     }
82 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/14820640.html