zoukankan      html  css  js  c++  java
  • 【题解】CF1320D Reachable Strings

    思路

    对于 1 并不好考虑,可以针对 0 考虑。

    发现每次移动会在一堆 1 之间移动把一个 0 移动 (2) 位,因此只需要记录所有 0 位置的奇偶性即可,具体实现可以用 Hash,对开头奇数/偶数分别开 Hash 表记录。

    这里 Hash 实现有一个方法:(BKDRHash)

    [h_i = ph_{i-1} + s_i ]

    这样可以非常容易地求出区间 Hash 值。(当然这里没写)

    不要 unsigned long long 自然溢出啊,会被卡爆的 ......

    Code

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define File(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
    typedef long long ll;
    typedef unsigned long long ull;
    template<typename T> inline void gi(T &x){
    	char ch; x = 0;
    	int f = 1;
    	while(isspace(ch = getchar()));
    	if(ch == '-') ch = getchar(), f = -1;
    	do x = x * 10 + ch - '0'; while(isdigit(ch = getchar()));
    	x *= f;
    }
    template<class T> void upmax(T &x, T y){x = x>y ? x : y;}
    template<class T> void upmin(T &x, T y){x = x<y ? x : y;}
    
    const int N = 200005;
    const ull p1 = 999983, p2 = 10007, mod1 = 104857601, mod2 = 167772161;
    char s[N];
    int cnt[N];
    
    template<ull p, ull mod>
    struct Hash{
    	ull h[N], pw[N];
    	int len;
    	Hash(){pw[0] = 1; len = 0; h[0] = 0;}
    	void hash(ull x){
    		++len;
    		pw[len] = pw[len - 1] * p % mod;
    		h[len] = (h[len - 1] + x * pw[len]) % mod;
    	}
    	void space(){
    		++len;
    		h[len] = h[len - 1];
    		pw[len] = pw[len - 1];
    	}
    	ull ask(int l, int r){
    		return (h[r] - h[l - 1] + mod) % mod;
    	}
    };
    Hash<p1, mod1> h01, h11;
    Hash<p2, mod2> h02, h12;
    
    int main(){
    	// File("cf1320d");
    	int n;
    	gi(n);
    	scanf("%s", s + 1);
    	for(int i=1; i<=n; i++){
    		if(s[i] == '1'){
    			h01.space(); h11.space(); h02.space(); h12.space();
    			cnt[i] = cnt[i-1];
    		}
    		else{
    			h01.hash((i & 1) + 1); h02.hash((i & 1) + 1);
    			h11.hash(((i & 1) ^ 1) + 1); h12.hash(((i & 1) ^ 1) + 1);
    			cnt[i] = cnt[i-1] + 1;
    		}
    	}
    	int q; gi(q);
    	while(q--){
    		int _l, _r, _len;
    		gi(_l); gi(_r); gi(_len);
    		int l1, r1, l2, r2;
    		l1 = _l; r1 = _l  + _len - 1; l2 = _r; r2 = _r + _len - 1;
    		if((cnt[r1] - cnt[l1 - 1]) != (cnt[r2] - cnt[l2 - 1])){
    			puts("No");
    			continue;
    		}
    		if((l1 ^ l2) & 1){
    			ull h1 = h01.ask(l1, r1) * h11.pw[l2 - 1] % mod1;
    			ull h2 = h11.ask(l2, r2) * h01.pw[l1 - 1] % mod1;
    			if(h1 != h2){
    				puts("No");
    				continue;
    			}
    			h1 = h02.ask(l1, r1) * h12.pw[l2 - 1] % mod2;
    			h2 = h12.ask(l2, r2) * h02.pw[l1 - 1] % mod2;
    			if(h1 != h2){
    				puts("No");
    				continue;
    			}
    		}
    		else{
    			ull h1 = h01.ask(l1, r1) * h01.pw[l2 - 1] % mod1;
    			ull h2 = h01.ask(l2, r2) * h01.pw[l1 - 1] % mod1;
    			if(h1 != h2){
    				puts("No");
    				continue;
    			}
    			h1 = h02.ask(l1, r1) * h02.pw[l2 - 1] % mod2;
    			h2 = h02.ask(l2, r2) * h02.pw[l1 - 1] % mod2;
    			if(h1 != h2){
    				puts("No");
    				continue;
    			}
    		}
    		puts("Yes");
    	}
    	return 0;
    }
    
  • 相关阅读:
    命令别名
    文件的元数据
    bash命令练习
    bash的使用
    Linux系统下的文件管理类常命令及使用方式
    Linux获取命令帮助、man文档章节的划分
    Linux目录名、命名规则及功能规定
    Linux命令使用格式
    springmvc 异常处理
    oracle 笔记一
  • 原文地址:https://www.cnblogs.com/RiverHamster/p/sol-cf1320d.html
Copyright © 2011-2022 走看看