[cf1392I]Kevin and Grid
称高温部分为红色、低温部分为蓝色,以下标$r,b$区分(通常均不带下标)
记$C$为连通块总数$,CI$为不与外部相连的连通块数,根据定义分数即$C+CI$
在网格图的基础上,建立以下平面图(以红色为例):
1.点集为网格图顶点满足周围四个格子中存在红色格子
2.边集为网格图线段满足两侧的格子中存在红色格子
记$s$为图中的连通块数,注意到$s_{r}=C_{r}$(不存在形如的状态)
又根据欧拉公式,有$s=v-e+f-1$(其中$v,e$和$f$分别为图中的点数、边数和面数)
记$cnt$为(原网格图中)格子个数,那么注意到$CI_{r}=f_{b}-cnt_{b}-1$(分析$f_{b}$中的面)
代入答案,即
$$
\begin{array}{ll}
(C_{r}+CI_{r})-(C_{b}+CI_{b})&=(v_{r}-e_{r}+f_{r}-1+f_{b}-cnt_{b}-1)-(v_{b}-e_{b}+f_{b}-1+f_{r}-cnt_{r}-1)\\&=v_{r}-e_{r}-cnt_{b}-v_{b}+e_{b}+cnt_{r}
\end{array}
$$
关于$v,e$和$cnt$均可使用fft预处理得到,时间复杂度为$o(n\log n)$,可以通过
1 #include<bits/stdc++.h> 2 #include<complex.h> 3 using namespace std; 4 #define N (1<<18) 5 #define PI acos(-1.0) 6 #define ll long long 7 #define cp complex<double> 8 struct pol{ 9 cp a[N]; 10 }x[3],y[3],z; 11 pair<int,int>qu[N]; 12 int n,m,q,a[N],b[N],rev[N]; 13 ll s[2][N],ans[N]; 14 void fft(pol &a,int p){ 15 for(int i=0;i<N;i++) 16 if (rev[i]<i)swap(a.a[i],a.a[rev[i]]); 17 for(int i=2;i<=N;i*=2){ 18 cp s=cp(cos(2*PI/i),sin(2*PI/i)); 19 if (p)s=conj(s); 20 for(int j=0;j<N;j+=i){ 21 cp ss=cp(1,0); 22 for(int k=0;k<(i>>1);k++,ss*=s){ 23 cp x=ss*a.a[j+k+(i>>1)]; 24 a.a[j+k+(i>>1)]=a.a[j+k]-x; 25 a.a[j+k]+=x; 26 } 27 } 28 } 29 } 30 void add(pol &a,int x,int y){ 31 fft(a,-1); 32 for(int i=0;i<N;i++){ 33 s[0][i]+=x*floor(a.a[i].real()/N+0.5); 34 s[1][i]+=y*floor(a.a[i].real()/N+0.5); 35 } 36 } 37 void init(){ 38 for(int i=0;i<N;i++)rev[i]=(i&1)*(N/2)+(rev[i>>1]>>1); 39 for(int i=1;i<=n;i++)x[0].a[a[i]]+=cp(1,0); 40 for(int i=1;i<=m;i++)y[0].a[b[i]]+=cp(1,0); 41 for(int i=0;i<=n;i++)x[1].a[max(a[i],a[i+1])]+=cp(1,0); 42 for(int i=0;i<=m;i++)y[1].a[max(b[i],b[i+1])]+=cp(1,0); 43 a[0]=a[n+1]=b[0]=b[m+1]=0x3f3f3f3f; 44 for(int i=0;i<=n;i++)x[2].a[min(a[i],a[i+1])]+=cp(1,0); 45 for(int i=0;i<=m;i++)y[2].a[min(b[i],b[i+1])]+=cp(1,0); 46 for(int i=0;i<3;i++){ 47 fft(x[i],0); 48 fft(y[i],0); 49 } 50 for(int i=0;i<N;i++)z.a[i]=x[0].a[i]*y[0].a[i]; 51 add(z,1,1); 52 for(int i=0;i<N;i++)z.a[i]=x[0].a[i]*y[1].a[i]; 53 add(z,-1,0); 54 for(int i=0;i<N;i++)z.a[i]=x[1].a[i]*y[0].a[i]; 55 add(z,-1,0); 56 for(int i=0;i<N;i++)z.a[i]=x[1].a[i]*y[1].a[i]; 57 add(z,1,0); 58 for(int i=0;i<N;i++)z.a[i]=x[0].a[i]*y[2].a[i]; 59 add(z,0,-1); 60 for(int i=0;i<N;i++)z.a[i]=x[2].a[i]*y[0].a[i]; 61 add(z,0,-1); 62 for(int i=0;i<N;i++)z.a[i]=x[2].a[i]*y[2].a[i]; 63 add(z,0,1); 64 } 65 int main(){ 66 scanf("%d%d%d",&n,&m,&q); 67 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 68 for(int i=1;i<=m;i++)scanf("%d",&b[i]); 69 init(); 70 for(int i=1;i<=q;i++){ 71 scanf("%d",&qu[i].first); 72 qu[i].second=i; 73 } 74 sort(qu+1,qu+q+1); 75 ll k=0; 76 for(int i=q,j=N-1;i;i--){ 77 while (qu[i].first<=j)k+=s[0][j--]; 78 ans[qu[i].second]=k; 79 } 80 k=0; 81 for(int i=1,j=0;i<=q;i++){ 82 while (j<qu[i].first)k+=s[1][j++]; 83 ans[qu[i].second]-=k; 84 } 85 for(int i=1;i<=q;i++)printf("%lld\n",ans[i]); 86 }