zoukankan      html  css  js  c++  java
  • BZOJ 4836 二元运算

    Description

    定义二元运算 opt 满足
    现在给定一个长为 n 的数列 a 和一个长为 m 的数列 b ,接下来有 q 次询问。每次询问给定一个数字 c 
    你需要求出有多少对 (i, j) 使得 a_i  opt b_j=c 。

    Input

    第一行是一个整数 T (1≤T≤10) ,表示测试数据的组数。
    对于每组测试数据:
    第一行是三个整数 n,m,q (1≤n,m,q≤50000) 。
    第二行是 n 个整数,表示 a_1,a_2,?,a_n (0≤a_1,a_2,?,a_n≤50000) 。
    第三行是 m 个整数,表示 b_1,b_2,?,b_m (0≤b_1,b_2,?,b_m≤50000) 。
    第四行是 q 个整数,第 i 个整数 c_i (0≤c_i≤100000) 表示第 i 次查询的数。

    Output

    对于每次查询,输出一行,包含一个整数,表示满足条件的 (i, j) 对的个数。

    Sample Input

    2
    2 1 5
    1 3
    2
    1 2 3 4 5
    2 2 5
    1 3
    2 4
    1 2 3 4 5

    Sample Output

    1
    0
    1
    0
    0
    1
    0
    1
    0
    1
    将数塞如一个桶,a[i]表示a中i这个数有多少个,b同样
    如果a[1]=2,b[3]=3,那么ans[4]+=a[1]*b[3]
    发现加法通过构造形成了卷积,减法通过反转也是卷积
    因为分两种情况,不能直接卷积
    分治时,考虑[l,mid]的数opt [mid+1,r]的数产生的答案
    用两个FFT解决
    此题卡常,不要用STL的向量
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<complex>
      7 using namespace std;
      8 typedef long long lol;
      9 const int NN=50005;
     10 double pi=acos(-1.0);
     11 struct data
     12 {
     13   double x,y;
     14 };
     15 data A[8*NN],B[8*NN];
     16 int R[8*NN],n,n1,n2,m,N;
     17 lol ans[8*NN],a[NN],b[NN];
     18 data operator + (const data &a,const data &b){
     19   return (data){a.x+b.x,a.y+b.y};
     20 }
     21 data operator - (const data &a,const data &b){
     22   return (data){a.x-b.x,a.y-b.y};
     23 }
     24 data operator * (const data &a,const data &b){
     25   return (data){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};
     26 }
     27 void FFT(data *D,int len,double o)
     28 {int i,j,k;
     29   for (i=0;i<len;i++)
     30     if (i<R[i]) swap(D[i],D[R[i]]);
     31   for (i=1;i<len;i<<=1)
     32     {
     33       data wn=(data){cos(pi/i),sin(o*pi/i)},x,y;
     34       for (j=0;j<len;j+=(i<<1))
     35     {
     36       data w=(data){1,0};
     37       for (k=0;k<i;k++,w=w*wn)
     38         {
     39           x=D[j+k];y=w*D[j+k+i];
     40           D[j+k]=x+y;
     41           D[j+k+i]=x-y;
     42         }
     43     }
     44     }
     45 }
     46 void solve(int l,int r)
     47 {int len,lg=0,i;
     48   if (l==r)
     49     return;
     50   int mid=(l+r)/2;
     51   len=1;
     52   while (len<=r-l+1) len*=2,lg++;
     53   for (i=0;i<len;i++)
     54     R[i]=(R[i>>1]>>1)|((i&1)<<(lg-1));
     55   for (i=0;i<len;i++)
     56     A[i]=B[i]=(data){0,0};
     57   for (i=l;i<=mid;i++)
     58     A[i-l]=(data){a[i],0};
     59   for (i=mid+1;i<=r;i++)
     60     B[i-mid-1]=(data){b[i],0};
     61   FFT(A,len,1);FFT(B,len,1);
     62   for (i=0;i<len;i++)
     63     A[i]=A[i]*B[i];
     64   FFT(A,len,-1);
     65   for (i=0;i<len;i++)
     66     ans[i+l+mid+1]+=(lol)(A[i].x/len+0.5);
     67   for (i=0;i<len;i++)
     68     A[i]=B[i]=(data){0,0};
     69   for (i=l;i<=mid;i++)
     70     A[mid-i]=(data){b[i],0};
     71   for (i=mid+1;i<=r;i++)
     72     B[i-mid-1]=(data){a[i],0};
     73   FFT(A,len,1);FFT(B,len,1);
     74   for (i=0;i<len;i++)
     75     A[i]=A[i]*B[i];
     76   FFT(A,len,-1);
     77   for (i=0;i<len;i++)
     78     ans[i+1]+=(lol)(A[i].x/len+0.5);
     79   solve(l,mid);solve(mid+1,r);
     80 }
     81 void work()
     82 {int i,j,x,q;
     83   memset(a,0,sizeof(a));
     84   memset(b,0,sizeof(b));
     85   scanf("%d%d%d",&n,&m,&q);
     86   for (i=1;i<=n;i++)
     87     {
     88       scanf("%d",&x);
     89       a[x]++;
     90       n1=max(n1,x);
     91     }
     92   for (i=1;i<=m;i++)
     93     {
     94       scanf("%d",&x);
     95       b[x]++;
     96       n2=max(n2,x);
     97     }
     98   memset(ans,0,sizeof(ans));
     99   N=max(n1,n2);
    100   for (i=1;i<=N;i++)
    101     ans[0]+=a[i]*b[i];
    102   solve(0,N);
    103   for (i=1;i<=q;i++)
    104     {
    105       scanf("%d",&x);
    106       printf("%lld
    ",ans[x]);
    107     }
    108 }
    109 int main()
    110 {int T;
    111   cin>>T;
    112   while (T--)
    113     work();
    114 }
  • 相关阅读:
    [转载]数据库外键的使用
    [转载]我如何筛选简历与选择人员
    [转载]asp.net中使用Row_Number函数分页
    五一,给心情放个假酷狗电台桌面版
    win32建立弹出式菜单
    GetMessage用法错误导致程序不能退出
    win32在程序当中引用菜单
    WM_COMMAND和WM_KEYDOWN消息的wParam,lParam参数
    单链表的释放内存free(delete)的顺序
    win32 GetMenu()和GetSubMenu()
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8386631.html
Copyright © 2011-2022 走看看