zoukankan      html  css  js  c++  java
  • CF1320D Reachable Strings

    一道挺好的题,刚刚开始的时候没什么思路,后来认真考虑了一些性质就会做了。

    题意是给出一个 01 串 (s)(|s| leq 2 imes 10^5),每次可将任意子串 (011) 变成 (110) 或者将 (110) 变成 (011)。有 (q) 次询问,每次询问两个等长的子串,询问是否可以从一个子串经过变换变成另一个子串。

    首先我们可以发现每次变换相当于把 (0) 向左或向右移动两位,移动前后相邻两个 (0) 之间 (1) 的个数奇偶不变,那么我们将这两个串中的 (0) 都尽量往某方向移动,如果移动之后两串长得一样,则这两原串间可相互变换。所以我们将每个 (0) 的权值设为与前一个 (0) 之间 (1) 个数的奇偶(也就是设成 digit % 2,其中 digit 表示前面所说的 (1) 的个数,然后用哈希判断是否相同即可。

    代码:

    #include <bits/stdc++.h>
    #define reg register
    #define ll long long
    #define ull unsigned long long
    #define db double
    #define pi pair<int, int>
    #define pl pair<ll, ll>
    #define vi vector<int>
    #define vl vector<ll>
    #define vpi vector<pi>
    #define vpl vector<pl>
    #define pb push_back
    #define er erase
    #define SZ(x) (int) x.size()
    #define lb lower_bound
    #define ub upper_bound
    #define all(x) x.begin(), x.end()
    #define rall(x) x.rbegin(), x.rend()
    #define mkp make_pair
    using namespace std;
    char ch, B[1 << 20], *S = B, *T = B;
    #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 20, stdin), S == T) ? 0 : *S++)
    #define isd(c) (c >= '0' && c <= '9')
    int aa, bb;
    int rd() {
      while(ch = getc(), !isd(ch) && ch != '-');
      ch == '-' ? aa = bb = 0 : (aa = ch - '0', bb = 1);
      while(ch = getc(), isd(ch))
        aa = aa * 10 + ch - '0';
      return bb ? aa : -aa;
    }
    const int MAXN = 2e5 + 10;
    const int BASE = 233;
    char s[MAXN];
    int n, a[MAXN], tot, flag[MAXN], cnt[MAXN];
    ull power[MAXN], Hash[MAXN];
    ull get(int l, int r) {
      int len = r - l + 1;
      return 1ll * Hash[r] - Hash[l - 1] * power[len];
    }
    ull check(int l, int r) {
      int L = lower_bound(a + 1, a + tot + 1, l) - a;
      int R = upper_bound(a + 1, a + tot + 1, r) - a - 1;
      if(L <= R) {
        ull x = (a[L] - l) & 1, v = x * power[R - L];
        if(L < R)
          v += get(L + 1, R);
        return v;
      }
      return 0;
    }
    inline void work() {
      power[0] = 1;
      for(reg int i = 1; i < MAXN; ++i)
        power[i] = power[i - 1] * BASE;
      scanf("%d%s", &n, s + 1);
      int digit = 0;
      for(reg int i = 1; i <= n; ++i) {
        cnt[i] = cnt[i - 1];
        if(s[i] == '1')
          digit++;
        else {
          flag[++tot] = digit & 1;
          digit = 0;
          a[tot] = i;
          ++cnt[i];
        }
      }
      for(reg int i = 1; i <= tot; ++i)
        Hash[i] = Hash[i - 1] * BASE + flag[i];
      int q;
      scanf("%d", &q);
      while(q--) {
        int l1, l2, len, r1, r2;
        scanf("%d%d%d", &l1, &l2, &len);
        r1 = l1 + len - 1;
        r2 = l2 + len - 1;
        if(cnt[r1] - cnt[l1 - 1] == cnt[r2] - cnt[l2 - 1] && check(l1, r1) == check(l2, r2))
          printf("Yes
    ");
        else
          printf("No
    ");
      }
    }
    int main() {
     	// freopen("input.txt", "r", stdin);
      work();
      return 0;
    }
    
  • 相关阅读:
    怎么在sublime里面显示编码格式
    鸟哥的Linux私房菜——第十七章:Linux 账号与身份管理
    反复
    鸟哥的Linux私房菜——第十六章:学习Shell Scripts
    鸟哥的Linux私房菜——第十五章:正规表示法
    鸟哥的Linux私房菜——第十四章:Bash Shell
    鸟哥的Linux私房菜——第十三章:Vim编译器
    Expression Blend实例中文教程(10)
    Expression Blend实例中文教程(9)
    Expression Blend实例中文教程(8)
  • 原文地址:https://www.cnblogs.com/Lonely-233/p/13659220.html
Copyright © 2011-2022 走看看