[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 }
View Code

 

posted @ 2020-10-03 13:10  PYWBKTDA  阅读(251)  评论(0编辑  收藏  举报