zoukankan      html  css  js  c++  java
  • BZOJ4836: [Lydsy1704月赛]二元运算【分治FFT】【卡常(没卡过)】

    Description

    定义二元运算 opt 满足

    img

    现在给定一个长为 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

    思路

    在上面两种情况中,减法可以把y取反直接fft,然后加法因为有限制可以在值域上进行分治fft

    然后其实很板子的。。。


    #include<bits/stdc++.h>
     
    using namespace std;
     
    typedef long long ll;
     
    namespace io {
     
    const int BUFSIZE = 1 << 20;
    char ibuf[BUFSIZE], *is = ibuf, *it = ibuf;
    char obuf[BUFSIZE], *os = obuf, *ot = obuf + BUFSIZE - 1;
     
    char read_char() {
      if (is == it)
        it = (is = ibuf) + fread(ibuf, 1, BUFSIZE, stdin);
      return *is++;
    }
     
    int read_int() {
      int x = 0, f = 1;
      char c = read_char();
      while (!isdigit(c)) {
        if (c == '-') f = -1;
        c = read_char();
      }
      while (isdigit(c)) x = x * 10 + c - '0', c = read_char();
      return x * f;
    }
     
    ll read_ll() {
      ll x = 0, f = 1;
      char c = read_char();
      while (!isdigit(c)) {
        if (c == '-') f = -1;
        c = read_char();
      }
      while (isdigit(c)) x = x * 10 + c - '0', c = read_char();
      return x * f;
    }
     
    void read_string(char* s) {
      char c = read_char();
      while (isspace(c)) c = read_char();
      while (!isspace(c)) *s++ = c, c = read_char();
      *s = 0;
    }
     
    void flush() {
      fwrite(obuf, 1, os - obuf, stdout);
      os = obuf;
    }
     
    void print_char(char c) {
      *os++ = c;
      if (os == ot) flush();
    }
     
    void print_int(int x) {
      static char q[20];
      if (!x) print_char('0');
      else {
        if (x < 0) print_char('-'), x = -x;
        int top = 0;
        while (x) q[top++] = x % 10 + '0', x /= 10;
        while (top--) print_char(q[top]);
      }
    }
     
    void print_ll(ll x) {
      static char q[20];
      if (!x) print_char('0');
      else {
        if (x < 0) print_char('-'), x = -x;
        int top = 0;
        while (x) q[top++] = x % 10 + '0', x /= 10;
        while (top--) print_char(q[top]);
      }
    }
     
    struct flusher_t {
      ~flusher_t() {
        flush();
      }
    } flusher;
     
    };
    using namespace io;
     
    const int N = 3e5 + 10;
    const int M = 5e4 + 10;
    const double eps = 1e-6;
    const double PI = acos(-1);
     
    typedef complex<double> Complex;
    typedef vector<Complex> Poly;
     
    Complex w[2][N];
     
    void init() {
      for (int i = 1; i < (1 << 18); i <<= 1) {
        w[0][i] = w[1][i] = Complex(1, 0);
        Complex wn(cos(PI / i), sin(PI / i));
        for (int j = 1; j < i; j++)
          w[1][i + j] = w[1][i + j - 1] * wn;
        wn = Complex(cos(PI / i), -sin(PI / i));
        for (int j = 1; j < i; j++)
          w[0][i + j] = w[0][i + j - 1] * wn;
      }
    }
     
    void transform(Complex *t, int len, int typ) {
      for (int i = 0, j = 0, k; j < len; j++) {
        if (i > j) swap(t[i], t[j]);
        for (k = (len >> 1); k & i; k >>= 1) i ^= k;
        i ^= k;
      }
      for (int i = 1; i < len; i <<= 1) {
        for (int j = 0; j < len; j += (i << 1)) {
          for (int k = 0; k < i; k++) {
            Complex x = t[j + k], y = w[typ][i + k] * t[j + k + i];
            t[j + k] = x + y;
            t[j + k + i] = x - y;
          }
        }
      }
      if (typ) return;
      for (int i = 0; i < len; i++)
        t[i] = Complex(t[i].real() / (double) len, t[i].imag());
    }
     
    bool equ0(double x) {
      return fabs(x) < eps;
    }
     
    Poly mul(const Poly a, const Poly b) {
      static Poly cura, curb;
      cura = a, curb = b;
      int len = 1 << (int) ceil(log2(cura.size() + curb.size() - 1));
      cura.resize(len), curb.resize(len);
      transform(&cura[0], len, 1);
      transform(&curb[0], len, 1);
      for (int i = 0; i < len; i++)
        cura[i] *= curb[i];
      transform(&cura[0], len, 0);
      return cura;
    }
     
    Poly ansadd(N, 0), anssub(N, 0);
    int n, m, q, maxa, maxb;
    int a[N], b[N];
    int cnta[N], cntb[N];
     
    void devide(int l, int r) {
      if (l == r) return;
      int mid = (l + r) >> 1;
      devide(l, mid);
      devide(mid + 1, r);
      Poly x, y;
      int sizl = mid - l + 1, sizr = r - mid;
      x.resize(sizl);
      y.resize(sizr);
      for (int i = 0; i < sizl; i++)
        x[i] = cnta[i + l];
      for (int i = 0; i < sizr; i++)
        y[i] = cntb[i + mid + 1];
      x = mul(x, y);
      for (int i = 0; i < (signed) x.size(); i++)
        ansadd[i + l + mid + 1] += x[i];
    }
     
    void calcadd() {
      devide(0, max(maxa, maxb));
    }
     
    void calcsub() {
      static Poly x, y;
      x.resize(maxb + maxa + 1);
      y.resize(maxb + maxa + 1);
      for (int i = 0; i <= maxb + maxa; i++)
        x[i] = y[i] = 0;
      for (int i = 0; i <= maxa; i++)
        x[maxb + i] = cnta[i];
      for (int i = 0; i <= maxb; i++)
        y[maxb - i] = cntb[i];
      x = mul(x, y);
      for (int i = maxb * 2; i < (signed) x.size(); i++)
        anssub[i - maxb * 2] = x[i];
    }
     
    void solve() {
      n = read_int(), m = read_int(), q = read_int();
      maxa = maxb = 0;
      for (int i = 1; i <= n; i++) {
        cnta[a[i] = read_int()]++;
        maxa = max(maxa, a[i]);
      }
      for (int i = 1; i <= m; i++) {
        cntb[b[i] = read_int()]++;
        maxb = max(maxb, b[i]);
      }
      calcsub();
      calcadd();
      while (q--) {
        int c = read_int();
        print_ll((ll) round(ansadd[c].real()) + (ll) round(anssub[c].real()));
        print_char('
    '); 
      }
      for (int i = 0; i <= maxa; i++)
        cnta[i] = 0;
      for (int i = 0; i <= maxb; i++)
        cntb[i] = 0;
      for (int i = 0; i <= maxa + maxb; i++)
        ansadd[i] = anssub[i] = 0;
    }
     
    int main() {
    #ifdef dream_maker
      freopen("input.txt", "r", stdin);
    #endif
      init();
      int T = read_int();
      while (T--) solve();
      return 0;
    }
    
  • 相关阅读:
    VS2008 环境中完美搭建 Qt 4.7.4 静态编译的调试与发布 Inchroy's Blog 博客频道 CSDN.NET
    编写可丢弃的代码
    c++ using namespace std; 海明威 博客园
    解决MySQL server has gone away
    nginx upstream 调度策略
    (2006, 'MySQL server has gone away') 错误解决 dba007的空间 51CTO技术博客
    Linux IO模型漫谈(2) 轩脉刃 博客园
    redis源码笔记 initServer 刘浩de技术博客 博客园
    MySQLdb批量插入数据
    词库的扩充百度百科的抓取你知道这些热词吗? rabbit9898 ITeye技术网站
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/10242332.html
Copyright © 2011-2022 走看看