Quailty and Binary Operation

Quailty and Binary Operation

题意

  • 分别给(N,M(N,M le 50000))两个数组(A)(B),满足(0 le A_i,B_i le 50000)
  • (Q(Q le 50000))次询问,每次求(a_i opt b_j = c)的对数((i,j))
  • [x opt y = egin{cases} x+y, if x<y, \ x-y, otherwise. end{cases} ]

思路

  • 分治+FFT

代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<time.h>
#include<stdlib.h>
#include<assert.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define sz(x) ((int)(x).size())
#define rep(i,l,r) for(int i=(l);i<(r);++i)
typedef long long ll;
typedef pair<int, int> pii;
const int N = (1 << 17) + 7;
const int INF = 1e9 + 7;
const int MOD = 1e9 + 7;
const double Pi = acos(-1.0);
const double EPS = 1e-8;
//--------head--------
struct FastIO {
	static const int S = 1310720;
	int wpos;
	char wbuf[S];
	FastIO() :
		wpos(0) {
		}
	inline int xchar() {
		static char buf[S];
		static int len = 0, pos = 0;
		if (pos == len)
			pos = 0, len = fread(buf, 1, S, stdin);
		if (pos == len)
			return -1;
		return buf[pos++];
	}
	inline int xuint() {
		int c = xchar(), x = 0;
		while (c <= 32)
			c = xchar();
		for (; '0' <= c && c <= '9'; c = xchar())
			x = x * 10 + c - '0';
		return x;
	}
	inline int xint() {
		int s = 1, c = xchar(), x = 0;
		while (c <= 32)
			c = xchar();
		if (c == '-')
			s = -1, c = xchar();
		for (; '0' <= c && c <= '9'; c = xchar())
			x = x * 10 + c - '0';
		return x * s;
	}
	inline void xstring(char *s) {
		int c = xchar();
		while (c <= 32)
			c = xchar();
		for (; c > 32; c = xchar())
			*s++ = c;
		*s = 0;
	}
	inline void wchar(int x) {
		if (wpos == S)
			fwrite(wbuf, 1, S, stdout), wpos = 0;
		wbuf[wpos++] = x;
	}
	inline void wint(int x) {
		if (x < 0)
			wchar('-'), x = -x;
		char s[24];
		int n = 0;
		while (x || !n)
			s[n++] = '0' + x % 10, x /= 10;
		while (n--)
			wchar(s[n]);
	}
	inline void wstring(const char *s) {
		while (*s)
			wchar(*s++);
	}
	~FastIO() {
		if (wpos)
			fwrite(wbuf, 1, wpos, stdout), wpos = 0;
	}
} io;
int n, m, q, a[N], b[N];
ll ans[N << 1];
int ca[N], cb[N];
struct C {
	double r, i;
	C() {
		r = i = 0;
	}
	C(double _r, double _i) {
		r = _r, i = _i;
	}
	C operator+(const C &p) const {
		return C(r + p.r, i + p.i);
	}
	C operator-(const C &p) const {
		return C(r - p.r, i - p.i);
	}
	C operator*(const C &p) const {
		return C(r * p.r - i * p.i, r * p.i + i * p.r);
	}
};
void fft(C x[], int n, int rev) {
	int i, j, k, t;
	for (i = 1; i < n; ++i) {
		for (j = 0, k = n >> 1, t = i; k; k >>= 1, t >>= 1)
			j = j << 1 | (t & 1);
		if (i < j)
			swap(x[i], x[j]);
	}
	int s, ds;
	for (s = 2, ds = 1; s <= n; ds = s, s <<= 1) {
		C w = C(1, 0), t;
		C wn = C(cos(2.0 * rev * Pi / s), sin(2.0 * rev * Pi / s));
		for (k = 0; k < ds; ++k, w = w * wn)
			for (i = k; i < n; i += s) {
				t = w * x[i + ds];
				x[i + ds] = x[i] - t;
				x[i] = x[i] + t;
			}
	}
	if (rev == -1)
		for (i = 0; i < n; ++i)
			x[i].r /= n;
}
C A[N], B[N], R[N];
void solve(int l, int r) {
	if (l > r) {
		return ;
	}
	if(r - l <= 30){
		for(int i=l;i<=r;++i){
			for(int j=l;j<=i;++j)
				ans[i-j] += 1ll * ca[i] * cb[j];
			for(int j=i+1;j<=r;++j)
				ans[i+j] += 1ll * ca[i] * cb[j];
		}
		return ;
	}
	int m = (l + r) >> 1, L = 1;
	while (L < r - l + 1)
		L <<= 1;
	solve(l, m), solve(m + 1, r);
	// x + y
	rep(i, 0, L) {
		A[i] = (l + i <= m ? C(ca[l + i], 0) : C(0, 0));
		B[i] = (m + i + 1 <=  r ? C(cb[m + 1 + i], 0) : C(0, 0));
	}
	fft(A, L, 1), fft(B, L, 1);
	rep(i, 0, L)
		R[i] = A[i] * B[i];
	fft(R, L, -1);
	rep(i, 0, L)
		ans[i + l + m + 1] += (ll) (R[i].r + 0.5);
	// x - y
	rep(i, 0, L) {
		A[i] = (m + 1 + i <=  r ? C(ca[m + 1 + i], 0) : C(0, 0));
		B[i] = (m - i >= l ? C(cb[m - i], 0) : C(0, 0));
	}
	fft(A, L, 1), fft(B, L, 1);
	rep(i, 0, L)
		R[i] = A[i] * B[i];
	fft(R, L, -1);
	rep(i, 0, L)
		ans[i + 1] += (ll) (R[i].r + 0.5);
}
int main() {
	int T = 10;
	T = io.xuint();
	rep(cas, 0, T) {
		n = io.xuint();
		m = io.xuint();
		q = io.xuint();
//		n = m = q = 50000;
//		rep(i, 0, n) a[i] = i, ++ca[a[i]];
//		rep(i, 0, m) b[i] = i, ++cb[b[i]];
		rep(i, 0, n) a[i] = io.xuint(), ++ca[a[i]];
		rep(i, 0, m) b[i] = io.xuint(), ++cb[b[i]];
		int mn = min(*min_element(a, a + n), *min_element(b, b + m));
		int mx = max(*max_element(a, a + n), *max_element(b, b + m));
//		printf("mn = %d, mx = %d
", mn, mx);
		solve(mn, mx);
		rep(_q, 0, q) {
			int x;
			x = io.xuint();
			printf("%lld
", ans[x]);	
		}
		rep(i, 0, 1 + (mx << 1))
			ans[i] = 0;
		rep(i, 0, n)
			ca[a[i]] = 0;
		rep(i, 0, m)
			cb[b[i]] = 0;
	}
	return 0;
}
原文地址:https://www.cnblogs.com/mcginn/p/5914576.html