zoukankan      html  css  js  c++  java
  • [百炼智能]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("
    ")
    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
    ", a[x] ? "YES" : "NO");
    	}
    }
    
  • 相关阅读:
    redis安装及简单命令
    struts2 第二天
    初学struts2-入门案列
    hibernate第二天
    hibernate入门
    同义词,索引,表分区
    表空间,序列
    orcale函数
    orcale错题分析
    orcale开篇
  • 原文地址:https://www.cnblogs.com/coldchair/p/13038434.html
Copyright © 2011-2022 走看看