热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

CF587FDuffisMad(AC自动机+树状数组+分块)

考虑两一个暴力1因为询问$[a,b]$可以拆成$[1,b]$$[1,a1]$所以把询问离线,然后就是求$[1,x]$中被$S_i$包含的串的数量。考虑当$[1,x1][1,x]$时

考虑两一个暴力

1

因为询问\([a,b]\)可以拆成\([1,b]\)-\([1,a-1]\)所以把询问离线,然后就是求\([1,x]\)中被\(S_i\)包含的串的数量。考虑当\([1,x-1]->[1,x]\)时我们把\(S_x\)结束节点在fail树的子树加1。然后询问就是求\(S_i\)在AC自动机上跑时经过所有点的点权用树状数组维护。设\(\sum{len[S_i]}=L\)这样的复杂度就是\(O(mLlogL)\)无法通过此题。

2

依然离线。这次我们把\(S_i\)放在fail树上跑时经过的点在fail树上加1。然后每一个x的贡献就是x的子树和。这个我们在fail树上DP(合并size)再做一个前缀合就能做到\(O(n)\)预处理\(O(1)\)查询。复杂度\(O(nL)\)无法通过此题。
然后我们对询问分块。长度大于\(sqrt(L)\)的用方法二,其他的用方法一。这样方法二最多用\(\sqrt{n}\)次。复杂度\(O(\sqrt{n}L)\)。方法一因为么次询问的串长最多为\(\sqrt{L}\),所以复杂度为\(O(m\sqrt{L}logL)\)最终复杂度就是这两个加起来。可以通过此题。

#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int N=201000;
const int M=501000;
int cnt,head[N];
int n,m;
long long ans[M];
int dfn[N],R[N],L[N],tot,LEN;
long long tr[N];
long long size[N],sum[N];
string s[N];
struct ques{
    int x,k,id;
    ques(int xx=0,int kk=0,int idd=0){
        x=xx;k=kk;id=idd;
    }
};
vector vec1[N],vec2[N];
struct edge{
    int to,nxt;
}e[N];
void add_edge(int u,int v){
    cnt++;
    e[cnt].nxt=head[u];
    e[cnt].to=v;
    head[u]=cnt;
}
int lowbit(int x){
    return x&-x;
}
void add(int x,int w){
    for(int i=x;i<=tot;i+=lowbit(i))tr[i]+=w;
}
long long getsum(int x){
    long long tmp=0;
    for(int i=x;i;i-=lowbit(i))tmp+=tr[i];
    return tmp;
}
void dfs(int u){
    dfn[u]=++tot;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        dfs(v);
    }
    R[u]=tot;
}
void dfs1(int u){
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        dfs1(v);
        size[u]+=size[v];
    }   
}
struct AC{
    int point[N],trans[N][27],tot,fail[N];
    void ins(string s,int len,int k){
        int now=0;
        for(int i=0;i q;
        for(int i=1;i<=26;i++)if(trans[0][i])q.push(trans[0][i]);
        while(!q.empty()){
            int now=q.front();
            q.pop();
            for(int i=1;i<=26;i++){
                if(trans[now][i])fail[trans[now][i]]=trans[fail[now]][i],q.push(trans[now][i]);
                else trans[now][i]=trans[fail[now]][i];
            }
        }
    }
}ac;
int read(){
    int sum=0,f=1;char ch=getchar();
    while(ch<&#39;0&#39;||ch>&#39;9&#39;){if(ch=&#39;-&#39;)f=-1;ch=getchar();}
    while(ch>=&#39;0&#39;&&ch<=&#39;9&#39;){sum=sum*10+ch-&#39;0&#39;;ch=getchar();}
    return sum*f;
}
int main(){
    n=read();m=read();
    for(int i=1;i<=n;i++){
        cin>>s[i];
        L[i]=s[i].size();
        LEN+=L[i];
        ac.ins(s[i],L[i],i);
    }
    int hhh=getchar();
    int block=sqrt(LEN);
    ac.get_fail();
    for(int i=1;i<=ac.tot;i++)add_edge(ac.fail[i],i);
    dfs(0);
    for(int i=1;i<=m;i++){
        int a=read(),b=read(),c=read();
        if(L[c]>block){
            vec1[c].push_back(ques(b,1,i)),vec1[c].push_back(ques(a-1,-1,i));
        }
        else vec2[a-1].push_back(ques(c,-1,i)),vec2[b].push_back(ques(c,1,i));
    }
    for(int i=1;i<=n;i++){
        int now=0;
        for(int j=0;j

CF587F Duff is Mad(AC自动机+树状数组+分块)


推荐阅读
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文介绍了指针的概念以及在函数调用时使用指针作为参数的情况。指针存放的是变量的地址,通过指针可以修改指针所指的变量的值。然而,如果想要修改指针的指向,就需要使用指针的引用。文章还通过一个简单的示例代码解释了指针的引用的使用方法,并思考了在修改指针的指向后,取指针的输出结果。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
author-avatar
薛薛Sying
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有