题目链接

Description

给定 \(n\) 个 \(01\) 模式串。\(q\) 次询问:

每次询问给定一个 \(01\) 串:

  • 设给这个串匹配的串是在模式串中存在的他的最长前缀
  • 问 \([a, b]\) 时刻内,这个匹配的串变了多少次。

Solution

这题很坑没有给出 \(01\) 串的长度数据范围,不过应该能读进来说明是个字符串总数的复杂度是够的。

统计两个串符合某种前缀关系,首先想到 \(\text{Trie}\)。

显然这个答案符合区间可加性,设答案 \(=\) 匹配串在前 \(r\) 个时刻的变换次数 \(-\) 匹配串在前 \(l\) 个时刻的变换次数。拆完询问后,不妨考虑离线,考虑从小到大加入一个模式串到 \(\text{Trie}\) 中,然后统计相应位置下的答案。

考虑在 \(Trie\) 树上动态维护每个节点的信息:

  • \(cnt_i\) 表示从开始到当前时刻,如果匹配串在这个节点,它的最长前缀会被修改多少次

比较显然的是,如果存在两个模式串 \(a,b\),\(a\) 是 \(b\) 的前缀。那么当 \(b\) 存在的时候,\(a\) 当前要进行加入 / 删除, \(a\) 的修改不会影响 \(b\) 节点的子树(因为 \(b\) 节点的子树的最长前缀还是 \(b\)),但是会影响 \(a\) 的子树除了 \(b\) 的子树的部分,让他们的 \(cnt\) 都 \(+1\)。这启示我们再弄一个信息:

  • \(st_i\) 表示 \(i\) 这个节点当前有没有模式串

那么每次修改 / 删除一个模式串 \(a\),就把 \(a\) 在 \(\text{Trie}\) 下的从上到下不断扩展,除非遇到 \(st\) 为 \(\text{True}\),那么停止。

然后我们发现这个东西其实和线段树的 \(\text{pushdown}\) 很像,然后再想想是可以这么搞的,弄个加法 \(\text{tag}\) 就行了,所以就 \(\text{OK}\) 了。值得注意的是 \(\text{pushdown}\) 仅能用在祖先全部处理完的情况下,不能胡乱加标记,否则修改的先后顺序会出现混乱,这是我之前尝试的(因为我不懂线段树 QAQ)。

时间复杂度

\(O(线性)\)

Code

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
using namespace std; const int N = 100005; int n, m, tr[N * 64][2], idx, cnt[N * 64];
int add[N * 64], pos[N], ans[N]; bool st[N * 64], opt[N]; char op[4], s[N][64], g[N][64]; vector<int> q[N]; void inline pushdown(int p) {
if (!add[p]) return;
if (!tr[p][0]) tr[p][0] = ++idx;
if (!tr[p][1]) tr[p][1] = ++idx;
if (!st[tr[p][0]]) add[tr[p][0]] += add[p], cnt[tr[p][0]] += add[p];
if (!st[tr[p][1]]) add[tr[p][1]] += add[p], cnt[tr[p][1]] += add[p];
add[p] = 0;
} void inline insert(int id, bool tag) {
int p = 0;
for (int i = 0; s[id][i]; i++) {
int ch = s[id][i] - '0';
pushdown(p);
if (!tr[p][ch]) tr[p][ch] = ++idx;
p = tr[p][ch];
}
cnt[p]++, add[p]++;
st[p] = tag;
} int inline query(int id) {
int p = 0;
for (int i = 0; g[id][i]; i++) {
int ch = g[id][i] - '0';
if (!tr[p][ch]) return cnt[p];
p = tr[p][ch];
pushdown(p);
}
return cnt[p];
} int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%s%s", op, s[i]);
opt[i] = op[0] == 'A';
}
for (int i = 1, a, b; i <= m; i++) {
scanf("%s%d%d", g[i], &a, &b);
q[a].push_back(i);
q[b].push_back(i);
}
for (int i = 1; i <= n; i++) {
insert(i, opt[i]);
for (int j = 0; j < q[i].size(); j++) {
int id = q[i][j];
ans[id] = query(id) - ans[id];
}
}
for (int i = 1; i <= m; i++) printf("%d\n", ans[i]);
return 0;
}

BJOI2016 IP地址的更多相关文章

  1. CentOS:ECDSA host key "ip地址" for has changed and you have requested strict checking(转)

    原文地址:http://blog.csdn.net/ausboyue/article/details/52775281 Linux SSH命令错误:ECDSA host key "ip地址& ...

  2. 烂泥:VMWare Workation双网卡配置IP地址

    本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb 前几天给一个客户做远程项目实施,客户那边的服务器是Windows OS的,我们这边的业务 ...

  3. xamarin android,UWP 网络类型和IP地址

    App开发经常要判断网络连通情况,并判断网络类型,获取网络IP.xamarin中可以使用Dependencies提供各平台下的方法,现把各平台代码记录如下: using System; using S ...

  4. C#服务器获取客户端IP地址以及归属地探秘

    背景:博主本是一位Windows桌面应用程序开发工程师,对网络通信一知半解.一日老婆逛完某宝,问:"为什么他们知道我的地址呢,他们是怎么获取我的地址的呢?" 顺着这个问题我们的探秘 ...

  5. windows下获取IP地址的两种方法

    windows下获取IP地址的两种方法: 一种可以获取IPv4和IPv6,但是需要WSAStartup: 一种只能取到IPv4,但是不需要WSAStartup: 如下: 方法一:(可以获取IPv4和I ...

  6. 【Win 10 应用开发】获取本机的IP地址

    按照老规矩,也是朋友的建议,老周今天在吹牛之前,先讲一个小故事. 有朋友问我,老周,你现在还发短信吗,你每个月用多少电话费?唉,实话说,现在真的发短信不多了,套餐送的130条短信,每月都发不了一条.至 ...

  7. 计算机网络学习笔记--网络层之IP地址与子网

    IPv4地址: 我们知道在网络层(TCP/IP体系结构的网际互联层),最重要的一个协议就是IP协议,现在正处于IPv4和IPv6的过渡时期,但目前来说,IPv4仍为主流,所以主要讲Ipv4. IP地址 ...

  8. Linux下的C Socket编程 -- 获取对方IP地址

    Linux下的C Socket编程(二) 获取域名对应的IP地址 经过上面的讨论,如果我们想要连接到远程的服务器,我们需要知道对方的IP地址,系统函数gethostbyname便能够实现这个目的.它能 ...

  9. 如何配置Linux系统的网络IP地址

    一台安装了Linux系统的电脑如果想要联网,首先要做的就是进行网络配置.今天小编就以CentOS6.4系统为例为大家介绍整个网络配置的过程,虽然只是以CentOS6.4系统为例,但是其它的Linux系 ...

随机推荐

  1. POSIX信号量与互斥锁实现生产者消费者模型

    posix信号量 Link with -lpthread. sem_t *sem_open(const char *name, int oflag);//打开POSIX信号量 sem_t *sem_o ...

  2. if __name__ == "__main__"的疑惑

    Python中if __name__ == "__main__"详细解释: 想必很多初次接触python都会见到这样一个语句,if __name__ == "__main ...

  3. [PHP安全特性学习]is_numeric()函数安全漏洞

    简介 PHP函数的安全特性-is_numerice() 函数 简介 PHP is_numeric() 函数 is_numeric() 函数用于检测变量是否为数字或数字字符串. 语法: bool is_ ...

  4. webug第十六关:明天双十一

    ---恢复内容开始--- 第十六关:明天双十一 不说了...只能看着源码做出来 ---恢复内容结束---

  5. C# 9 record 并非简单属性 POCO 的语法糖

    C# 9 record 并非简单属性 POCO 的语法糖 最近升级专案到大统一 .NET 5 并使用 C#9 语法尝试改写套件,发现之前以为 record 只是简单属性 POCO 的简化语法糖的认知是 ...

  6. 计算机&编程语言发展史

    计算机&编程语言发展史 编辑于2020-11-18 计算机的基本组成 计算机的发展经历了哪几代? 第一代 电子管计算机 第二代 晶体管计算机 第三代 集成电路计算机 第四代 大规模和超大规模集 ...

  7. 企业级工作流解决方案(十一)--集成Abp和ng-alain--权限系统服务

    权限系统主要定义为管理员增删改查权限数据,直接读取数据库,权限系统服务主要定义为供其他系统调用的权限验证接口,定义为两个不同的微服务. 权限系统有一个特点,数据变动比较小,数据量本身并不是很大,访问量 ...

  8. HBase高级特性、rowkey设计以及热点问题处理

    在阐述HBase高级特性和热点问题处理前,首先回顾一下HBase的特点:分布式.列存储.支持实时读写.存储的数据类型都是字节数组byte[],主要用来处理结构化和半结构化数据,底层数据存储基于hdfs ...

  9. 在CorelDRAW中如何完成属性的复制

    复制功能在任何一个编辑软件中都是必不可少.使用率很高的一个功能,在矢量图形设计软件CorelDRAW 中也不例外.关于对象的复制这里就不过多示意了,主要为大家示范一下如何在设计中复制对象的一些属性. ...

  10. 如何使用系统清理缓存软件优化MacBook

    在我们使用我们的Mac一定的时间后,总是不可避免的出现Mac内存不足的情况,所以清理垃圾软件也就成为了我们电脑里必不可少的软件.苹果软件商店中有很多各有不同的清理垃圾软件,但我们往往很难从这一大堆软件 ...