zoukankan      html  css  js  c++  java
  • 棠梨煎雪

    题目背景

    岁岁花藻檐下共将棠梨煎雪

    自总角至你我某日辗转天边

    天淡天青 宿雨沾襟

    一年一会信笺却只见寥寥数言

    ——银临《棠梨煎雪》

    题目描述

    扶苏正在听《棠梨煎雪》的时候,@spitfirekindergarten 发来一道IOI2018集训队作业题:我切了这集训队题,辣鸡扶苏快过来做题。扶苏定睛一看,这不s*题嘛,写了一发交上去才发现自己看错题目了。但是写完的代码不能浪费,于是就有了这道题。

    歌词中的主人公与她的朋友一年会有一次互相写信给对方,一共通信了 mm 年。为了简化问题,我们认为她们每封信的内容都是一条二进制码,并且所有二进制码的长度都是 nn。即每封信的内容都是一个长度为 nn的字符串,这个字符串只含字符 0 或 1

    这天她拿出了朋友写给她的所有信件,其中第 ii 年的写的信件编号为 ii。由于信件保存时间过久,上面有一些字符已经模糊不清,我们将这样的位置记为 ?? 字符可以被解释为 0 或 1。由于她的朋友也是人,符合人类的本质,所以朋友在一段连续的时间中书写的内容可能是相同的。现在她想问问你,对于一段连续的年份区间 [l,~r][l, r] 中的所有信件,假如朋友在这段时间展示了人类的本质,所写的是同一句话,那么这一句话一共有多少种可能的组成。也即一共有多少字符串 SS,满足在这个区间内的所有信件的内容都可能是 SS。

    一个长度为 nn 的只含 0,1,? 的字符串 AA 可能是一个字符串 BB 当且仅当 BB 满足如下条件:

    BB 的长度也是 nn

    BB 中只含字符 0,1

    AA 中所有为 0 的位置在 BB 中也是 0

    AA 中所有为 1 的位置在 BB 中也是 1

    AA 中为 ? 的位置在 BB 中可以为 0 也可以是 1

    同时她可能会突然发现看错了某年的信的内容,于是她可能会把某一年的信的内容修改为一个别的只含 0,1,? 的长度为 nn 的字符串。

    输入格式

    每个输入文件中都有且仅有一组测试数据。

    输入数据第一行为三个正整数 n,~m,~qn, m, q,代表字符串长度,字符串个数和操作次数。

    下面 mm 行,每行是一个长度为 nn 的字符串,第 ii 个字符串代表第 ii 年信的内容。

    下面 qq 行,每行的第一个数字是操作编号 optopt。

    如果 opt=0opt=0,那么后面接两个整数 [l,~r][l, r],代表一次查询操作

    如果 opt=1opt=1,那么后面接一个整数 pospos,在一个空格后会有一个长度为 nn 的字符串,代表将第 pospos 个字符串修改为新的字符串。

    输出格式

    为了避免输出过大,请你输出一行一个数代表所有查询的答案异或和对 00 取异或的结果

    输入输出样例

    输入 #1
    3 3 5
    010
    0?0
    1?0
    0 1 2
    0 2 3
    1 3 0??
    0 2 3
    0 1 3
    输出 #1
    2

    说明/提示

    样例解释

    对于第一次询问,只有串 010 符合要求

    对于第二次询问,由于第二个串的第一位为 1,第三个串的第一位为 0,故没有串符合要求

    修改后将第三个串修改为 0??

    对于第四次询问,有两个串符合要求,分别为 000 和 010

    对于第五次询问,只有 010 符合要求。

    故答案为1 0 2 1,他们的异或和再异或 00 的值为2

    数据范围

    本题采用多测试点捆绑测试

    各个子任务的数据范围见下表

    qwq

    部分子任务可能会出现卡常的情况,请注意常数因子对程序效率造成的影响

    请注意输入的问号为嘤文问号,即其 ASCII 码值为 6363。

    我们保证数据是在Linux下生成的,即换行符不含

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int maxn = 1e5 + 8;
    const int N = 36;
    int n, m, q;
    char str[maxn][N];
    int f[maxn << 2][N];
    struct data {
        int s, t;
    };
    
    data operator|(data p, data q) {
        return (data) {p.s | q.s, p.t | q.t};
    }
    
    inline void pushup(int rt) {
        f[rt][0] = f[rt << 1][0] | f[rt << 1 | 1][0];
        f[rt][1] = f[rt << 1][1] | f[rt << 1 | 1][1];
    }
    
    inline void build(int l, int r, int rt) {
        if (l == r) {
            int len = strlen(str[l] + 1);
            for (register int i = 1; i <= n; ++i) {
                if (str[l][i] == '?')continue;
                f[rt][str[l][i] - '0'] |= (1 << (i - 1));
                //printf("debug f[%d][str[l][i]] = %d
    ", rt, f[rt][str[l][i] - '0']);
            }
            return;
        }
        int mid = l + r >> 1;
        build(l, mid, rt << 1);
        build(mid + 1, r, rt << 1 | 1);
        pushup(rt);
    }
    
    inline void update(int l, int r, int rt, int pos, char *s) {
        if (l == r) {
            f[rt][0] = f[rt][1] = 0;
            for (register int i = 0; i < n; ++i) {
                if (s[i] == '?')continue;
                f[rt][s[i] - '0'] |= (1 << i);
            }
            return;
        }
        int mid = l + r >> 1;
        if (pos <= mid)update(l, mid, rt << 1, pos, s);
        else update(mid + 1, r, rt << 1 | 1, pos, s);
        pushup(rt);
    }
    
    inline data query(int l, int r, int ql, int qr, int rt) {
        if (ql <= l && qr >= r) {
            return (data) {f[rt][0], f[rt][1]};
        }
        int mid = l + r >> 1;
        if (qr <= mid) {
            return query(l, mid, ql, qr, rt << 1);
        } else if (ql > mid) {
            return query(mid + 1, r, ql, qr, rt << 1 | 1);
        } else {
            return query(l, mid, ql, qr, rt << 1) | query(mid + 1, r, ql, qr, rt << 1 | 1);
        }
    }
    
    char tp[36];
    int res;
    
    int main() {
        //freopen("1.txt", "r", stdin);
        scanf("%d%d%d", &n, &m, &q);
        for (register int i = 1; i <= m; ++i) {
            scanf("%s", str[i] + 1);
        }
        build(1, m, 1);
        int op;
        while (q--) {
            scanf("%d", &op);
            if (op == 0) {
                int l, r;
                scanf("%d%d", &l, &r);
                data cur = query(1, m, l, r, 1);
                int ans = 1;
                //printf("debug cur.s = %d cur.t = %d
    ", cur.s, cur.t);
                for (register int i = 1; i <= n; ++i) {
                    if ((cur.s & 1) && (cur.t & 1)) {
                        ans = 0;
                        break;
                    }
                    if (!(cur.s & 1) && !(cur.t & 1)) {
                        ans *= 2;
                    }
                    cur.s >>= 1;
                    cur.t >>= 1;
                }
                //printf("debug ans = %d
    ", ans);
                res = res ^ ans;
                //printf("debug res = %d
    ", res);
            } else {
                int id;
                scanf("%d%s", &id, tp + 1);
                update(1, m, 1, id, tp + 1);
            }
        }
        printf("%d
    ", res);
        return 0;
    }
  • 相关阅读:
    Python并发(一)
    Python协程详解(二)
    Python协程详解(一)
    Python装饰器
    ●BZOJ 3676 [Apio2014]回文串
    ●POJ 3974 Palindrome(Manacher)
    ●BZOJ 1692 [Usaco2007 Dec]队列变换
    ●BZOJ 4698 Sdoi2008 Sandy的卡片
    ●BZOJ 4516 [Sdoi2016]生成魔咒
    ●BZOJ 3238 [Ahoi2013]差异
  • 原文地址:https://www.cnblogs.com/czy-power/p/11414564.html
Copyright © 2011-2022 走看看