[玲珑OJ1044] Quailty and Binary Operation (FFT+cdq分治)

题目链接

题意:给定两个长度为n的数组a与长度为m的数组b, 给定一个操作符op满足 x op y = x < y ? x+y : x-y.  有q个询问,每次给出询问c,问:有多少对(i, j)满足a[i] op b[j] = c ?

0 <= c <= 100000, 其余数据范围在[0, 50000].

 

题解:问题的关键在于如何分隔开 x < y与x >= y. cdq分治,合并的时候a[l, mid]与b[mid+1, r]卷积一次计算a[] < b[] , a[mid+1, r]与b[l, mid]再卷积一次a[] > b[]即可。

卡时,memset的时候优化了一下。

 1 #include <bits/stdc++.h>
 2 typedef long long ll;
 3 using namespace std;
 4 const int N = 1e5+5;
 5 struct comp{
 6     double r,i;comp(double _r=0,double _i=0){r=_r;i=_i;}
 7     comp operator+(const comp x){return comp(r+x.r,i+x.i);}
 8     comp operator-(const comp x){return comp(r-x.r,i-x.i);}
 9     comp operator*(const comp x){return comp(r*x.r-i*x.i,r*x.i+i*x.r);}
10 }x[N<<1], y[N<<1];
11 const double pi=acos(-1.0);
12 void FFT(comp a[],int n,int t){
13     for(int i=1,j=0;i<n-1;i++){
14         for(int s=n;j^=s>>=1,~j&s;);
15         if(i<j)swap(a[i],a[j]);
16     }
17     for(int d=0;(1<<d)<n;d++){
18         int m=1<<d,m2=m<<1;
19         double o=pi/m*t;comp _w(cos(o),sin(o));
20         for(int i=0;i<n;i+=m2){
21             comp w(1,0);
22             for(int j=0;j<m;j++){
23                 comp &A=a[i+j+m],&B=a[i+j],t=w*A;
24                 A=B-t;B=B+t;w=w*_w;
25             }
26         }
27     }
28     if(t==-1)for(int i=0;i<n;i++)a[i].r/=n;
29 }
30 int a[N], b[N], n, m, q;
31 ll ans[N];
32 void cdq(int l, int r){
33     if(l == r){
34         ans[0] += a[l]*b[l];
35         return;
36     }
37     int mid = l+r >> 1;
38     cdq(l, mid);
39     int len = 1;
40     while(len <= (r-l+1)) len <<= 1;
41     memset(x, 0, sizeof(comp)*len );
42     memset(y, 0, sizeof(comp)*len );
43     for(int i = l; i <= mid; i++)
44         x[i-l] = comp(a[i], 0);
45     for(int i = mid+1; i <= r; i++)
46         y[i-mid-1] = comp(b[i], 0);
47     FFT(x, len, 1); FFT(y, len, 1);
48     for(int i = 0; i < len; i++)
49         x[i] = x[i]*y[i];
50     FFT(x, len, -1);
51     for(int i = l+mid+1; i <= mid+r; i++)
52         ans[i] += x[i-l-mid-1].r+0.5;
53     for(int i = 0; i < len; i++)
54         x[i] = y[i] = comp(0, 0);
55     for(int i = mid+1; i <= r; i++)
56         x[i-mid-1] = comp(a[i], 0);
57     for(int i = l; i <= mid; i++)
58         y[mid+1-i] = comp(b[i], 0);
59     FFT(x, len, 1); FFT(y, len, 1);
60     for(int i = 0; i < len; i++)
61         x[i] = x[i]*y[i];
62     FFT(x, len, -1);
63     for(int i = 1; i <= r-l; i++)
64         ans[i] += x[i].r+0.5;
65     cdq(mid+1, r);
66 }
67 
68 int main(){
69     int t, x, maxn; scanf("%d", &t);
70     while(t--){
71         scanf("%d%d%d", &n, &m, &q);
72         maxn = 0;
73         for(int i = 0; i < n; i++){
74             scanf("%d", &x);
75             maxn = max(maxn, x);
76             a[x]++;
77         }
78         for(int i = 0; i < m; i++){
79             scanf("%d", &x);
80             maxn = max(maxn, x);
81             b[x]++;
82         }
83         cdq(0, maxn);
84         while(q--){
85             scanf("%d", &x);
86             printf("%lld\n", ans[x]);
87         }
88         memset(a, 0, sizeof(int)*(maxn+3));
89         memset(b, 0, sizeof(int)*(maxn+3));
90         memset(ans, 0, sizeof(ll)*(maxn*2+3));
91     }
92     return 0;
93 }
View Code

 

posted @ 2016-10-06 22:45  我在地狱  阅读(370)  评论(0编辑  收藏  举报