zoukankan      html  css  js  c++  java
  • [玲珑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
    ", 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
  • 相关阅读:
    Go part 7 反射,反射类型对象,反射值对象
    activemq BytesMessage || TextMessage
    Go part 6 接口,接口排序,接口嵌套组合,接口与类型转换,接口断言
    mysql 查询表的字段名称,字段类型
    冒泡(bubblesort)、选择排序、插入排序、快速排序
    用 python 写一个模拟玩家移动的示例
    day 14(作业)
    day 13
    day 12
    day 11
  • 原文地址:https://www.cnblogs.com/dirge/p/5935137.html
Copyright © 2011-2022 走看看