protagonist

棠梨煎雪

题目背景

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

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

天淡天青 宿雨沾襟

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

——银临《棠梨煎雪》

题目描述

扶苏正在听《棠梨煎雪》的时候,@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下生成的,即换行符不含\r

#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\n", 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\n", 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\n", ans);
            res = res ^ ans;
            //printf("debug res = %d\n", res);
        } else {
            int id;
            scanf("%d%s", &id, tp + 1);
            update(1, m, 1, id, tp + 1);
        }
    }
    printf("%d\n", res);
    return 0;
}

 

posted @ 2019-08-26 19:59  czy-power  阅读(244)  评论(0编辑  收藏  举报