zoukankan      html  css  js  c++  java
  • BZOJ 4836: [Lydsy1704月赛]二元运算

    给定的数组不好操作,把他弄成桶,存出现的次数。

    然后我们发现如果都是$x+y$或者都是$x-y$就是一个卷积,用FFT就行了。

    那考虑分治,对于$[l,mid]$和$[mid+1,r]$两段。

    要么左区间选$a$数组,要么右区间选。

    然后递归处理即可。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define LL long long
      4 inline int read() {
      5     char ch = getchar(); int x = 0, f = 1;
      6     while(ch < '0' || ch > '9') {
      7         if(ch == '-') f = -1;
      8         ch = getchar(); 
      9     }
     10     while('0' <= ch && ch <= '9') {
     11         x = x * 10 + ch - '0';
     12         ch = getchar();
     13     }
     14     return x * f;
     15 }
     16 int aa[50010], bb[50010];
     17 LL cnt[200010];
     18 struct com{
     19     double r, i;
     20     com(){
     21         r = i = 0;
     22     }
     23     com(double a, double b) {
     24         r = a, i = b;
     25     }
     26     com operator + (const com& x) const {
     27         return com(r + x.r, i + x.i);
     28     }
     29     com operator - (const com& x) const {
     30         return com(r - x.r, i - x.i);
     31     }
     32     com operator * (const com& x) const {
     33         return com(r * x.r - i * x.i, r * x.i + i * x.r);
     34     }
     35 } A[200010], B[200010], w[200010];
     36 const double PI = acos(-1.0);
     37 int rev[200010];
     38 inline void FFT(com a[], int n) {
     39     for(int i = 0; i < n; ++ i) {
     40         if(rev[i] > i) {
     41             swap(a[rev[i]], a[i]);
     42         }
     43     }
     44     for(int t = n >> 1, d = 1; d < n; d <<= 1, t >>= 1) {
     45         for(int i = 0; i < n; i += (d << 1)) {
     46             for(int j = 0; j < d; ++ j) {
     47                 com tmp = w[t * j] * a[i + j + d];
     48                 a[i + j + d] = a[i + j] - tmp;
     49                 a[i + j] = a[i + j] + tmp;
     50             }
     51         }
     52     }
     53 }
     54 inline int Do(int n, int m) {
     55     int L = 0, N = 1;
     56     for(; N <= n + m; N <<= 1, ++ L);
     57     for(int i = 0; i < N; ++ i) {
     58         rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (L - 1));
     59         w[i] = com(cos(2.0 * i * PI / N), sin(2.0 * i * PI / N));
     60     }
     61     FFT(A, N); FFT(B, N);
     62     for(int i = 0; i < N; ++ i) {
     63         A[i] = A[i] * B[i];
     64         w[i].i = -w[i].i;
     65     }
     66     FFT(A, N);
     67     return N;
     68 }
     69 inline void solve(int l, int r) {
     70     if(l == r) {
     71         cnt[0] += 1ll * aa[l] * bb[l];
     72         return;
     73     }
     74     int mid = (l + r) / 2;
     75     for(int i = l, j = 0; i <= mid; ++ i, ++ j) {
     76         A[j] = com(aa[i], 0);
     77     }
     78     for(int i = mid + 1, j = 0; i <= r; ++ i, ++ j) {
     79         B[j] = com(bb[i], 0);
     80     }
     81     int N = Do(mid - l + 1, r - mid);
     82     for(int i = 0; i <= r - l - 1; ++ i) {
     83         cnt[l + mid + 1 + i] += (LL)(A[i].r / N + 0.5);
     84     }
     85     for(int i = 0; i < N; ++ i) {
     86         A[i] = com(0, 0);
     87         B[i] = com(0, 0);
     88     }
     89     for(int i = mid + 1, j = 0; i <= r; ++ i, ++ j) {
     90         A[j] = com(aa[i], 0);
     91     }
     92     for(int i = mid, j = 0; i >= l; -- i, ++ j) {
     93         B[j] = com(bb[i], 0);
     94     }
     95     N = Do(r - mid, mid - l + 1);
     96     for(int i = 0; i <= r - l - 1; ++ i) {
     97         cnt[i + 1] += (LL)(A[i].r / N + 0.5);
     98     }
     99     for(int i = 0; i < N; ++ i) {
    100         A[i] = com(0, 0);
    101         B[i] = com(0, 0);
    102     }
    103     solve(l, mid); solve(mid + 1, r);
    104 }
    105 inline void solve() {
    106     int n = read(), m = read(), q = read();
    107     memset(aa, 0, sizeof(aa));
    108     memset(bb, 0, sizeof(bb));
    109     memset(cnt, 0, sizeof(cnt));
    110     for(int i = 1; i <= n; ++ i) {
    111         ++ aa[read()];
    112     }
    113     for(int i = 1; i <= m; ++ i) {
    114         ++ bb[read()];
    115     }
    116     solve(0, 50000);
    117     while(q --) {
    118         int x = read();
    119         printf("%lld
    ", cnt[x]);
    120     }
    121 }
    122 int main() {
    123     int T = read();
    124     while(T --) {
    125         solve();
    126     }
    127 }
  • 相关阅读:
    flex
    IOCP三:多个接收
    IOCP三:多个接收
    IOCP二:同时发送和接收
    IOCP二:同时发送和接收
    IOCP一:AcceptEx
    IOCP一:AcceptEx
    字符串和数字相互转换
    字符串和数字相互转换
    QThread应用详解
  • 原文地址:https://www.cnblogs.com/iamqzh233/p/11028677.html
Copyright © 2011-2022 走看看