Codeforces 472G Design Tutorial: Increase the Constraints(分块+FFT)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <bits/stdc++.h>
using namespace std;


#define N 550020
#define LL long long
#define MOD 1000000007
#define K 3
#define G 3


const int B = 6000;

int n, m;
char s[N], t[N];
int len;
int rev[N];
const double Pi = acos(-1.0);

struct cd {
	double r, i;
	cd() {}
	cd(double r, double i):r(r), i(i) {}

	cd operator + (const cd &b) const {
		return cd(r + b.r, i + b.i);
	}
	cd operator - (const cd &b) const {
		return cd(r - b.r, i - b.i);
	}
	cd operator * (const cd &b) const {
		return cd(r * b.r - i * b.i, i * b.r + r * b.i);
	}
}x1[N], x2[N];

void change(cd y[], int len) {
	for(int i = 1; i < len; ++i) {
		rev[i] = (rev[i>>1] >> 1) + (i & 1) * (len >> 1);
		if(i < rev[i]) swap(y[i], y[rev[i]]);
	}
}
void FFT(cd y[], int len, int on) {
	change(y, len);
	for(int h = 2; h <= len; h <<= 1) {
		cd wn(cos(on * 2 * Pi / h), sin(on * 2 * Pi / h));
		for(int j = 0; j < len; j += h) {
			cd w(1, 0);
			for(int k = j; k < j + h / 2; ++k) {
				cd u = y[k];
				cd t = w * y[k+h/2];
				y[k] = u + t;
				y[k+h/2] = u - t;
				w = w * wn;
			}
		}
	}
	if(on == -1) {
		for(int i = 0; i < len; ++i) y[i].r /= len;
	}
}

void debug() {
	cd x1[4] = {cd(-1, 0), cd(-1, 0)};
	cd x2[4] = {cd(1, 0), cd(1, 0)};
	FFT(x1, 4, 1);
	FFT(x2, 4, 1);
	for(int i = 0; i < 4; ++i) x1[i] = x1[i] * x2[i];
	FFT(x1, 4, -1);
	for(int i = 0; i < 4; ++i) printf("%.3lf ", floor(x1[i].r + 0.5));
	puts("");
}
	

short int cnt[200020/B][N];

int main() {
	scanf("%s%s", s, t);
	n = strlen(s);
	m = strlen(t);
	len = 1;
	while(len <= n + m) len <<= 1;

	

	for(int i = 0; i + B < n; i += B) {
		for(int j = 0; j < len; ++j) {
			if(j < m) {
				int v = t[j] == '1'? 1: -1;
				x2[m-j-1] = cd(v, 0);
			}
			else x2[j] = cd(0, 0);
			if(j >= i && j < i + B) {
				int v = s[j] == '1'? 1: -1;
				x1[j] = cd(v, 0);
			}
			else x1[j] = cd(0, 0);
		}
		FFT(x1, len, 1);
		FFT(x2, len, 1);
		for(int j = 0; j < len; ++j) x1[j] = x1[j] * x2[j];
		FFT(x1, len, -1);
		for(int j = 0; j < len; ++j) cnt[i/B][j] = (int)floor(x1[j].r + 0.5);
	}
	int q;
	scanf("%d", &q);
	while(q--) {
		int a, b, x;
		scanf("%d%d%d", &a, &b, &x);
		int l = a, r = a + x - 1;
		int u = l / B, v = r / B;

		int ans = 0;
		if(u == v) {
			for(int i = 0; i < x; ++i) {
				if(s[i+a] != t[b+i]) ans++;
			}
		}
		else {
			for(int i = l % B, j = 0; i < B; ++i, ++j) {
				if(s[a+j] != t[b+j]) ++ans;
			}
			for(int i = 0, j = r % B; i <= r % B; ++i, --j) 
				if(s[r-j] != t[b+x-1-j]) ++ans;
			for(int k = u + 1; k < v; ++k) {
				ans += (B - cnt[k][a+m-b-1]) / 2;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值