正题

题目链接:https://www.luogu.com.cn/problem/P7046


题目大意

给出一个长度为 nnn 的字符串,然后 mmm 次把它的一个子串加入集合。如果一个字符串在这个集合中作为字符串的后缀出现次数大于 kkk 那么这个字符串就会被计入贡献。
每次求计入贡献的字符串数和最长长度。

1≤n,m≤5×105,0≤k<n1\leq n,m\leq 5\times 10^5,0\leq k<n1≤n,m≤5×105,0≤k<n。


解题思路

考虑在parents树上如果能定位到一个节点的字符串那么它的后缀就是它到根的路径。

但是可能定位不到根,一种暴力的做法是每条边上建一个线段树然后暴力改。但是这样很麻烦可以考虑让每个询问一定能定位到一个节点。

我们直接建好树然后每次把询问倍增挂到对应的边上用set储存,然后再重新建一棵包含每个节点的树。

那么现在问题就变为了统计子树权值大于 kkk 的节点了,因为每个点到根的路径上满足条件的边一定是一段后缀,而每个节点最多统计一次,所以我们直接每次倍增找到最上面的没有统计的节点用树状数组+dfsdfsdfs 序判断是否合法就好了。

时间复杂度:O(nlog⁡n)O(n\log n)O(nlogn)(默认 n,mn,mn,m 同级)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#define lowbit(x) (x&-x)
using namespace std;
const int M=1e6+10,N=2e6+10,T=21;
struct node{int to,next;
}a[N];
int n,m,k,last,cnt,tot,ans2;long long ans1;
int ch[M][26],len[N],fa[N],L[M],R[M],p[M],las[M];
int ls[N],v[N],pos[N],f[N][T],rfn[N],ed[N],dos[M];
set<int> ct[M];vector<int> q[M];char s[M];
set<int>::iterator it;
void Insert(int c){int p=last,np=last=++cnt;len[np]=len[p]+1;for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;if(!p)fa[np]=1;else{int q=ch[p][c];if(len[q]==len[p]+1)fa[np]=q;else{int nq=++cnt;len[nq]=len[p]+1;memcpy(ch[nq],ch[q],sizeof(ch[nq]));fa[nq]=fa[q];fa[q]=fa[np]=nq;for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;}}return;
}
void work(int p,int l,int r){int x=pos[r];for(int i=T-1;i>=0;i--)if(len[f[x][i]]>=r-l+1)x=f[x][i];if(ct[x].count(r-l+1))return;ct[x].insert(r-l+1);q[x].push_back(p);return;
}
void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
bool cmp(int x,int y)
{return R[x]-L[x]+1<R[y]-L[y]+1;}
bool cMp(int x,int y)
{return len[x]<len[y];}
void dfs(int x){rfn[x]=++cnt;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;f[y][0]=x;dfs(a[i].to);}ed[x]=cnt;return;
}
struct TreeBinary{int t[N];void Change(int x,int val){while(x<=n){t[x]+=val;x+=lowbit(x);}return;}int Ask(int x){int ans=0;while(x){ans+=t[x];x-=lowbit(x);}return ans;}
}B;
int main()
{scanf("%d%d%d",&n,&m,&k);scanf("%s",s+1);cnt=last=1;for(int i=1;i<=n;i++)Insert(s[i]-'a'),pos[i]=last;for(int i=1;i<=cnt;i++)f[i][0]=fa[i];for(int j=1;j<T;j++)for(int i=1;i<=cnt;i++)f[i][j]=f[f[i][j-1]][j-1];for(int i=1;i<=m;i++){scanf("%d%d",&L[i],&R[i]);work(i,L[i],R[i]);}for(int i=1;i<=cnt;i++)p[i]=i,ct[i].insert(len[i]);sort(p+1,p+1+cnt,cMp);int pnt=cnt;cnt=1;las[1]=1;for(int i=2;i<=pnt;i++){int x=p[i];sort(q[x].begin(),q[x].end(),cmp);int z=0;las[x]=las[fa[x]];it=ct[x].begin();while(1){++cnt;addl(las[x],cnt);las[x]=cnt;int W=*it;len[cnt]=*it;while(z<q[x].size()&&R[q[x][z]]-L[q[x][z]]+1<=W)dos[q[x][z]]=cnt,z++;it++;if(it==ct[x].end())break;}}n=cnt;cnt=0;dfs(1);v[0]=1;len[0]=-1;for(int j=1;j<T;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];for(int i=1;i<=m;i++){int p=dos[i];if(!p){printf("%lld %d\n",ans1,ans2);continue;}B.Change(rfn[p],1);if(v[p]){printf("%lld %d\n",ans1,ans2);continue;}while(!v[p]){int x=p;for(int j=T-1;j>=0;j--)if(!v[f[x][j]])x=f[x][j];int w=B.Ask(ed[x])-B.Ask(rfn[x]-1);if(w>k){v[x]=1;ans1+=len[x]-len[f[x][0]];ans2=max(ans2,len[x]);}else break;}printf("%lld %d\n",ans1,ans2);}return 0;
}

P7046-「MCOI-03」诗韵【SAM,倍增,树状数组】相关推荐

  1. 「模拟赛20180307」三元组 exclaim 枚举+树状数组

    题目描述 给定 \(n,k\) ,求有多少个三元组 \((a,b,c)\) 满足 \(1≤a≤b≤c≤n\)且\(a + b^2 ≡ c^3\ (mod\ k)\). 输入 多组数据,第一行数据组数\ ...

  2. LG5200 「USACO2019JAN」Sleepy Cow Sorting 树状数组

    \(\mathrm{Sleepy Cow Sorting}\) 问题描述 LG5200 题解 树状数组. 设\(c[i]\)代表\([1,i]\)中归位数. 显然最终的目的是将整个序列排序为一个上升序 ...

  3. POJ2182 Lost Cows(树状数组、二分、倍增)

    Lost Cows 题目链接 Description N (2 <= N <= 8,000) cows have unique brands in the range 1-N. In a ...

  4. 2023牛客寒假算法基础集训营4_20230130「向上取整」「夹逼dp」「lowbit科学+树状数组性质」「搜索」「倍增跳表」「莫队」

    6/13 教育场是有被教育到.(预计会鸽几题. 已过非太水的题们 //B //https://ac.nowcoder.com/acm/contest/46812/B//小构造小数学#include & ...

  5. loj #535. 「LibreOJ Round #6」花火 树状数组求逆序对+主席树二维数点+整体二分...

    $ \color{#0066ff}{ 题目描述 }$ 「Hanabi, hanabi--」 一听说祭典上没有烟火,Karen 一脸沮丧. 「有的哦-- 虽然比不上大型烟花就是了.」 还好 Shinob ...

  6. 「雅礼集训 2017 Day7」事情的相似度(后缀自动机+LCT+树状数组)

    description 点击查看题目内容 solution Step1 无脑建SAMSAMSAM 两个前缀的最长公共后缀就是parent−treeparent-treeparent−tree上两点的l ...

  7. 【bzoj4009】[HNOI2015]接水果 DFS序+树上倍增+整体二分+树状数组

    题目描述 给出一棵n个点的树,给定m条路径,每条路径有一个权值.q次询问求一个路径包含的所有给定路径中权值第k小的. 输入 第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数. 接下来n ...

  8. HDU 6203 ping ping ping (在线倍增lca+DFS序+树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6203 #include<bits/stdc++.h> using namespace st ...

  9. 「数据压缩03」WAV及AVI的文件格式分析

    目录 wav简介:​​​​​​​ 格式分析: RIFT区块: FORMAT区块: ​ DATA区块: 实例分析: wav简介:​​​​​​​ Waveform Audio File Format(WA ...

最新文章

  1. CSS Selector 3
  2. VTK修炼之道5_Procedural Source Object
  3. delphi之模糊找图
  4. Linux文件系统及磁盘分区与格式化(二次排版)
  5. 机器学习资料升级版来了!!!
  6. linux远程桌面太卡,确保远程桌面管理顺畅稳定的方法
  7. 1×pbs缓冲液配方_PBS缓冲液配方.doc
  8. 唐太宗灵州勒石 TANGTAIZONGLINZHOULESHI
  9. robot_marm catkin_make报错
  10. pytonh mysql_python操作Mysql实例代码教程(查询手册)
  11. 学院新闻报道,邹老师光临指导
  12. 查询条件中含有加号_中国邮储银行信用卡公众号账单查询
  13. springboot返回时间有错解决方案
  14. jQuery实现简单日历
  15. python程序设计实验指导书第1版实验三十四_《python编程基础》实验指导书.doc
  16. 创建Android工程心德,Android项目的个人总结
  17. 解决导入curses包的时候出现ModuleNotFoundError: No module named ‘_curses‘的问题
  18. 高等教育发展对产业结构升级的促进作用研究
  19. 数学基础--学习笔记
  20. 2020年Java前景如何?现在还适合入行吗?

热门文章

  1. js获取int类型长度_js代码比较大小前需要把string转换int
  2. oracle体系结构和组件图示,Oracle 体系结构组件
  3. adf盖怎么打开_罐头好吃盖难开,学会这几招,再不靠蛮力了,女生也轻松拧开...
  4. 国内linux内核镜像仓库,国内较快的maven仓库镜像
  5. require引入js vue_请教 关于使用require 引入vue 和公共js的问题
  6. java buffalo_随你怎么玩!Buffalo 网络硬盘新潮流
  7. case when影响性能吗_字段为NULL会影响查询性能吗?
  8. 河南信息工程学校计算机组装比赛,计算机技术系承办2019全员化试点项目计算机网络装调赛项...
  9. 好用的平板电脑_平板选择华为M6,这里有几点建议
  10. 使用Microsoft Word2016无法正常对Latex文本转换的踩坑和解决方法