• LOJ#6500. 「雅礼集训 2018 Day2」操作 题解


    首先考虑一个 (Theta(nm)) 的暴力。

    一次操作对差分数组的影响是把两个距离相差k的位置都异或上1,那么我们只需要保证对于模 k 的每个余数的位置上的1的总数为偶数即可,并且答案为相邻两个的位置差的和 / k。

    那么对于每组询问,我们只需要做一个差分即可。判断是否有解可以考虑哈希。需要注意细节。

    (Theta(n+m+k))

    code :

    #include <bits/stdc++.h>
    #define LL unsigned long long
    using namespace std;
    template <typename T> void read(T &x){
    	static char ch; x = 0,ch = getchar();
    	while (!isdigit(ch)) ch = getchar();
    	while (isdigit(ch)) x = x * 10 + ch - '0',ch = getchar();
    }
    inline void write(int x){ if (x > 9) write(x/10); putchar(x%10+'0'); }
    inline void Get(bool &x){
    	static char ch; ch = getchar();
    	while (!(ch == '0' || ch == '1')) ch = getchar();
    	x = ch - '0';
    }
    const int N = 2000005;
    int n,k,m,s[N][2],now[N]; LL sum[N],hv[N],pre[N]; bool a[N];
    int main(){
    	int i;
    	read(n),read(k),read(m); srand(time(NULL));
    	for (i = 1; i <= n; ++i) Get(a[i]);
    	for (i = 0; i < k; ++i) hv[i] = ((LL)rand() << 45) + ((LL)rand() << 30ull) + ((LL)rand() << 15ull) + (LL)rand();
    	for (i = 1; i <= n; ++i){
    		pre[i] = pre[i-1],sum[i] = sum[i-1];
    		if (a[i] ^ a[i-1]){
    			pre[i] ^= hv[i%k];
    			sum[i] += i - (now[i%k] << 1);
    			now[i%k] = i - now[i%k];
    		}
    		s[i][0] = now[i%k],s[i][1] = now[(i+1)%k];
    	}
    	int l,r; LL Hash,ret;
    	while (m--){
    		read(l),read(r);
    		Hash = pre[l] ^ pre[r] ^ (a[l] ? hv[l%k] : 0) ^ (a[r] ? hv[(r+1)%k] : 0);
    		if (Hash){ putchar('-'),putchar('1'),putchar('
    '); continue; }
    		ret = sum[r] - sum[l];
    		if (a[l]) ret -= l - (s[l][0] << 1);
    		if (a[r]) ret += (r+1) - (s[r][1] << 1);
    		ret /= k;
    		write(ret),putchar('
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    AOJ 2200 Mr. Rito Post Office
    poj 3259 Wormholes
    01背包求解组合最值问题
    01背包求解面值组成问题
    金明的预算方案
    追赶法
    有关动态规划的一些定理。。。。。
    4980
    并查集
    快速幂
  • 原文地址:https://www.cnblogs.com/s-r-f/p/13701014.html
Copyright © 2020-2023  润新知