zoukankan      html  css  js  c++  java
  • bzoj 4836: [Lydsy2017年4月月赛]二元运算 -- 分治+FFT

    4836: [Lydsy2017年4月月赛]二元运算

    Time Limit: 8 Sec  Memory Limit: 128 MB

    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

    HINT

     

    Source

    可能我的常数真的巨大。。。

    转载一个姜大爷的题解 http://blog.csdn.net/neither_nor/article/details/70889246

    #include<map>
    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define inf 1000000007
    #define ll long long
    #define PI acos(-1)
    #define M 400010
    inline int rd()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    #define db double
    struct cl{
        db x,y;
        cl(){}
        cl(db _x,db _y){x=_x;y=_y;}
        friend cl operator +(const cl &x,const cl &y){return cl(x.x+y.x,x.y+y.y);}
        friend cl operator -(const cl &x,const cl &y){return cl(x.x-y.x,x.y-y.y);}
        friend cl operator *(const cl &x,const cl &y){return cl(x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x);}
        friend cl operator /(const cl &x,const db &y){return cl(x.x/y,x.y/y);}
        cl con(){return cl(x,-y);}
    };
    cl a[M],b[M];
    int n,L,R[M];
    int A[M],B[M],mx,T;
    ll ans[M];
    void fft(cl *x,int f,int n)
    {
        for(int i=0;i<n;i++) if(i<R[i]) swap(x[i],x[R[i]]);
        for(int i=1;i<n;i<<=1)
        {
            cl wn(cos(PI/i),f*sin(PI/i));
            for(int j=0;j<n;j+=(i<<1))
            {
                cl w(1,0),X,Y;
                for(int k=0;k<i;k++,w=w*wn)
                {
                    X=x[j+k];Y=w*x[j+k+i];
                    x[j+k]=X+Y;x[j+k+i]=X-Y;
                }
            }
        }
        if(f==-1) for(int i=0;i<n;++i) x[i]=x[i]/n;
    }
    void cal(int l,int r,int n,int L)
    {
        if(l==r)
        {
            ans[0]+=(ll)A[l]*B[l];
            return ;
        }
        register int i,j,mid=l+r>>1;
        for(i=0;i<n;++i) R[i]=(R[i>>1]>>1)|((i&1)<<L);
        for(i=0;i<n;++i) a[i]=b[i]=cl(0,0);
        for(i=l;i<=mid;++i) a[i-l].x=A[i];
        for(i=mid+1;i<=r;++i) a[i-mid-1].y=B[i];
        fft(a,1,n);
        for(i=0;i<n;i++)
        {
            j=(n-i)&(n-1);
            b[i]=(a[i]*a[i]-(a[j]*a[j]).con())*cl(0,-0.25);
        }
        fft(b,-1,n);
        for(i=0;i<n;++i) ans[l+mid+1+i]+=(ll)(b[i].x+0.1);
        
        for(i=0;i<n;++i) a[i]=b[i]=cl(0,0);
        for(i=mid+1;i<=r;i++) a[i-mid-1].x=A[i];
        for(i=l;i<=mid;i++) a[mid-i].y=B[i];
        fft(a,1,n);
        for(i=0;i<n;i++)
        {
            j=(n-i)&(n-1);
            b[i]=(a[i]*a[i]-(a[j]*a[j]).con())*cl(0,-0.25);
        }
        fft(b,-1,n);
        for(i=0;i<n;++i) ans[1+i]+=(ll)(b[i].x+0.1);
        
        cal(l,mid,n>>1,L-1);
        cal(mid+1,r,n>>1,L-1);
    }
    int main()
    {
        register int n1,n2,q,i,x;
        T=rd();
        while(T--)
        {
            n1=rd();n2=rd();q=rd();mx=0;
            memset(A,0,sizeof(A));
            memset(B,0,sizeof(B));
            memset(ans,0,sizeof(ans));
            for(i=0;i^n1;++i)
            {
                x=rd();A[x]++;
                mx=max(mx,x);
            }
            for(i=0;i^n2;i++)
            {
                x=rd();B[x]++;
                mx=max(mx,x);
            }
            for(n=1,L=-1;n<(mx<<1);n<<=1) L++;
            cal(0,n-1,n,L);
            while(q--)
            {
                x=rd();
                printf("%lld
    ",ans[x]);
            }
        }
        return 0;
    }
  • 相关阅读:
    flume,kafka不在一个内网互相打通.md
    尚硅谷Flink2020教程.md
    常用命令.md
    四象限工作效率-事件管理.md
    甘特图目标实施-进度管控.md
    PDCA循环法.md
    SMART大目标拆解小目标.md
    基于内外部竞争环境和竞争条件下的态势分析
    使用Java正则表达式批量提取文本信息
    使用markdown高效编写博客(创建标题)
  • 原文地址:https://www.cnblogs.com/lkhll/p/7372596.html
Copyright © 2011-2022 走看看