[cf1392I]Kevin and Grid

令$v$为点数(有公共点的格子中存在红/蓝色)、$e$为边数(有公共边的格子中存在红/蓝色)、$f$为以此法(即仅考虑这些点和边)所分割出的区域数(包括外面)、$s$为连通块个数,将欧拉定理简单扩展,可以得到$v-e+f=s+1$

(对于样例1中红点部分,有$v=16$、$e=24$、$f=10$、$s=1$;对于蓝点部分,有$v=36$、$e=52$、$f=19$、$s=2$)

令$s_{r/b}'$表示红/蓝色中不在边界上的连通块个数,那么答案为$(v_{b}-e_{b}+v_{r}-e_{r})+(f_{b}-f_{r}+s'_{b}-s'_{r})$,令$f'_{b}=f_{b}-s'_{r}$,$f'_{r/b}$即为红/蓝色的格子数量+1(每一个在其内部的另一种颜色的连通块必然恰好对应一个不是红色格子或最外部的区域)

因此,即求出$v/e/f'_{r/b}$,以$f'_{r}$为例,令$f(x)=sum_{i=1}^{n}x^{a_{i}}sum_{i=1}^{m}x^{b_{i}}$,则$f(x)=sum_{i=k}^{infty}f(x)[i]$($f(x)[i]$表示$f(x)$的$x^{i}$项系数),用fft计算即可(需要13次fft)

 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
",ans[i]);
86 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/13763974.html