[百炼智能]hihoCoder挑战赛37 D Items(树状数组维护01背包—梦想成真!!!)

http://hihocoder.com/contest/challenge37/problem/4

  • 考虑每次都是把一段或到另一段去。

  • 也就是说要快速找到原来段1,新的段0的位置

  • 结论:(1,0)的个数=(0,1)的个数

  • 证明:设增量是\(x\)\(a[i]\)\(a[(i+x)~mod~m]\)连边,可以发现若有\((0,1)\),则迟早会出现\((1,0)\)

  • 那么只要找到不同的位置,树状数组维护hash值,每次二分lcp即可,复杂度\(O(m~log^2~m)\)

Code:

#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;

const ll mo = 23333333333333333ll;

ll mul(ll x, ll y) {
	ll z = (long double) x * y / mo;
	z = x * y - z * mo;
	if(z < 0) z += mo; else if(z >= mo) z -= mo;
	return z;
}

const int W = 29;

const int N = 3e5 + 5;

ll w[N];
int n, m, x;

#define low(x) ((x) & -(x))

ll f[N];
void add(int x, ll y) {
	x ++;
	for(; x <= m; x += low(x)) f[x] = (f[x] + y) % mo;
}
ll sum(int x) {
	x ++;
	ll s = 0;
	for(; x; x -= low(x)) s += f[x];
	return (s % mo + mo) % mo;
}

int d[N], d0, a[N];

int pd(int x, int y, int l, int r) {
	if(x > l) swap(x, l), swap(y, r);
	ll s1 = (sum(y) - sum(x - 1) + mo) % mo;
	ll s2 = (sum(r) - sum(l - 1) + mo) % mo;
	return mul(s1, w[l - x]) == s2;
}

int ef(int p, int q) {
	if(p > q) swap(p, q);
	int as = 0;
	for(int l = 1, r = m - q; l <= r; ) {
		int d = l + r >> 1;
		if(pd(p, p + d - 1, q, q + d - 1)) as = d, l = d + 1; else r = d - 1;
	}
	return as;
}

void solve(int x, int y, int l, int r) {
	if(x > y) return;
	while(x <= y && l <= r) {
		int g = ef(x, l);
		if(x + g - 1 >= y) return;
		d[++ d0] = l + g;
		x += g + 1, l += g + 1;
	}
} 

int main() {
	scanf("%d %d", &n, &m);
	w[0] = 1; fo(i, 1, m) w[i] = w[i - 1] * W % mo;
	a[0] = 1; add(0, w[0]);
	fo(ii, 1, n) {
		scanf("%d", &x);
		x %= m;
		d0 = 0;
		solve(0, m - x - 1, x, m - 1);
		solve(m - x, m - 1, 0, x - 1);
		fo(i, 1, d0) {
			x = d[i];
			if(!a[x]) {
				a[x] = 1;
				add(x, w[x]);
			}
		}
	}
	int Q; scanf("%d", &Q);
	fo(ii, 1, Q) {
		scanf("%d", &x);
		pp("%s\n", a[x] ? "YES" : "NO");
	}
}
posted @ 2020-06-03 16:35  Cold_Chair  阅读(175)  评论(0编辑  收藏  举报