码迷,mamicode.com
首页 > 其他好文 > 详细

【题解】CF1320D Reachable Strings

时间:2020-03-08 17:47:03      阅读:57      评论:0      收藏:0      [点我收藏+]

标签:inline   turn   开头   each   sig   记录   amp   void   signed   

思路

对于 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;
}

【题解】CF1320D Reachable Strings

标签:inline   turn   开头   each   sig   记录   amp   void   signed   

原文地址:https://www.cnblogs.com/RiverHamster/p/sol-cf1320d.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!