BZOJ4836 二元運算 分治FFT

2022-03-27 09:32:43 字數 2674 閱讀 4163

time limit: 8 sec  memory limit: 128 mb

submit: 578  solved: 202

[submit][status][discuss]

定義二元運算 opt 滿足

現在給定乙個長為 n 的數列 a 和乙個長為 m 的數列 b ,接下來有 q 次詢問。每次詢問給定乙個數字 c 

你需要求出有多少對 (i, j) 使得 a_i  opt b_j=c 。

第一行是乙個整數 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 次查詢的數。

對於每次查詢,輸出一行,包含乙個整數,表示滿足條件的 (i, j) 對的個數。

22 1 5

1 32

1 2 3 4 5

2 2 5

1 32 4

1 2 3 4 510

1001

0101

鳴謝tangjz提供試題

[submit][status][discuss]

挺有意思的一道題,應該不難想到是分治fft,主要是cdq分治函式內部要想得很清楚。

首先如果只有加法,就是裸卷積。

如果只有減法,那麼有$c_k=\sum\limits_^na_ib_$,把b翻轉,最後將c前移n位即可$c_=\sum\limits_^na_b_$

現在有了大小關係的限制,我們可以通過$cdq$分治處理。

首先特判掉相等的情況,然後對於$[l,r]$這個區間,將$[l,mid]$和$[mid+1,r]$遞迴處理,現在問題只剩下$a[l,mid]$和$b[mid+1,r]$,$a[mid+1,r]$和$b[l,mid]$兩個問題了。

顯然前乙個問題直接將$a$前移$l$位,$b$前移$mid+1$位,卷起來之後再後移$l+mid+1$位即可。後乙個問題,將$a$前移$mid+1$位,b翻轉後前移$l$位,這樣卷之後的區間下標是從$0$開始的,而我們的差是從$1$開始的,所以右移$1$位。

卷的時候還是一定要注意次數界!ntt也可以。

1 #include2 #include3 #include4 #include5

#define mem(a) memset(a,0,sizeof(a))

6 typedef long

long

ll;7

using

namespace

std;89

const

int n=500010;10

const

double pi=acos(-1

.);11

struct ca[n],b[n];

12int

a[n],b[n],rev[n],n,t,x,m,q,mx,len1,len2;

13ll ans[n];

1415 c operator +(c &a,c &b); }

16 c operator -(c &a,c &b); }

17 c operator *(const c &a,const c &b); }

1819

void dft(c a,int n,int

f);23

for (int p=i<<1,j=0; jp);

25for (int k=0; kwn)28}

29}30if (f==1) return;31

for (int i=0; in;32}

3334

void cdq(int l,int

r);41

for (int i=l; i<=mid; i++) a[i-l].x=a[i];

42for (int i=mid+1; i<=r; i++) b[i-mid-1].x=b[i];

43 dft(a,n,1); dft(b,n,1

);44

for (int i=0; ib[i];

45 dft(a,n,-1

);46

for (int i=0; i1+l]+=(ll)(a[i].x+0.5

);47

48for (int i=0; i0,0

};49

for (int i=mid+1; i<=r; i++) a[i-mid-1].x=a[i];

50for (int i=l; i<=mid; i++) b[mid-i].x=b[i];

51 dft(a,n,1); dft(b,n,1

);52

for (int i=0; ib[i];

53 dft(a,n,-1

);54

for (int i=0; i1]+=(ll)(a[i].x+0.5

);55 cdq(l,mid); cdq(mid+1

,r);56}

5758

intmain()

69return0;

70 }

BZOJ4836 二元運算(分治FFT)

設a n 為a中n的個數,b n 為b中n的個數。如果只考慮加法顯然是乙個卷積,減法翻轉一下也顯然是乙個卷積。問題在於兩者都有。容易想到分開處理。那麼可以考慮分治。即對於值域區間 l,r 分別計算a l,mid 和b mid 1,r 的貢獻及a mid 1,r 和b l,mid 的貢獻,然後再遞迴處...

bzoj 4836 二元運算

死活tle.求助 update 4.3 23 08 求助了tls之後終於過了.分治裡次數界寫崩了.r l 1就行.分治的做法很神奇!本題的限制在於操作型別與權值相對大小有關,而用 l,mid 更新 mid 1,r 正好適應了本題的要求 include include include include ...

二元運算子過載

siwuxie095 二元運算子過載 所謂 二元運算子,即 這個符號與兩個運算元進行運算 1 加號 的過載 加號 的過載方式有兩種 一種是友元函式過載,一種是成員函式過載 1 先來看成員函式過載,如下 定義乙個座標類 coordinate 在類中宣告成員函式 operator 它的引數是 const...