[NBUT 1646 Internet of Lights and Switches] 前缀异或和+二分

来源:互联网 发布:钱刷宝提示网络异常 编辑:程序博客网 时间:2024/05/22 10:38

[NBUT 1646 Internet of Lights and Switches] 前缀异或和+二分

题目链接:[NBUT 1646 Internet of Lights and Switches]
题意描述:N 个灯, M 个开关,每个开关可以控制多个灯。每个开关对应一个01串,第 i 位为0 表示 这个开关不能控制第i 盏灯, 为1 表示能够控制。初始灯是全亮的。你可以按一个连续区间的开关使得灯全灭,区间的长度必须是在[a, b],问 有多少种 方法可以使灯全灭。每个开关只能按一次。
解题思路:显然,按区间[L, R] 的开关等价于 先按一次[1, L - 1],  然后再按一次[L, R] 区间的开关。所以我们首先需要处理出前 i 盏灯的 前缀异或和, 用pre[] 表示。 要让灯全灭, 就相当于找出区间[L, R], 满足 这个区间 的异或和全为1。 也就等价于pre[R] ^ pre[L - 1] 全1。知道这个就简单很多了。我们只需要枚举区间左端点,然后二分区间右端点。然后求出区间长度就OK了。
#include <queue>#include <cmath>#include <cstdio>#include <string>#include <cstring>#include <iostream>#include <algorithm>using namespace std;//#pragma comment(linker, "/STACK:1024000000,1024000000")#define FIN             freopen("input.txt","r",stdin)#define FOUT            freopen("output.txt","w",stdout)#define fst             first#define snd             secondtypedef __int64  LL;typedef pair<int, int> PII;typedef pair<LL, LL> PLL;const double eps = 1e-10;const int MAXN = 50 + 5;const int MAXM = 300000 + 5;const int INF  = 0x3f3f3f3f;int T, N, M, A, B;char buf[MAXN];LL pre[MAXM], X, Y, E;PLL data[MAXM];LL F (char s[]) {    LL ret = 0LL;    for (int i = 0; s[i]; i++) {        ret = (ret << 1) + s[i] - '0';    }    return ret;}int main() {#ifndef ONLINE_JUDGE    FIN;//     FOUT;#endif // ONLINE_JUDGE    int cas = 0;    LL res;    while (~scanf ("%d %d %d %d", &N, &M, &A, &B) ) {        res = E = pre[0] = 0LL;        for (int i = 1; i <= N; i++) {            E = (E << 1) | 1;        }        data[0] = PLL (0, 0);        for (int i = 1; i <= M; i++) {            scanf ("%s", buf);            X = F (buf);            pre[i] = pre[i - 1] ^ X;            data[i].fst = pre[i];            data[i].snd = i;        }        sort (data, data + M + 1);        for (int i = 0; i <= M; i++) {            X = data[i].fst;            Y = data[i].snd;            int a = lower_bound (data + 1, data + M + 1, PLL (X ^ E, Y + A) ) - data;            int b = upper_bound (data + 1, data + M + 1, PLL (X ^ E, Y + B) ) - data;            if (a > M) continue;            res += (b - a);        }        printf ("Case %d: %I64d\n", ++cas, res);    }    return 0;}

0 0
原创粉丝点击