题目传送门

题意简述:给出 \(s\),多次询问给出长度分别为 \(k,l\) 的序列 \(a,b\),求 \(\sum_{i=1}^k\sum_{j=1}^l\mathrm{LCP}(s[a_i:n],s[b_j:n])\)。

Yet Another 套路题。


如果你做过 P4248 [AHOI2013]差异 应该可以很快秒掉这题。

我们先对 \(s\) 进行后缀排序,求出 height 数组,并将 \(a_i,b_i\) 替换为 \(rk_{a_i},rk_{b_i}\),那么题目就变为 \(\sum_{i=1}^k\sum_{j=1}^l\min_{k=\min(a_i,b_i)+1}^{\max(a_i,b_i)}ht_k\)。

预处理出 \(ht\) 的 ST 表以 \(\mathcal{O}(1)\) RMQ。然后使用类似上面那题的套路,单调栈求出答案。

具体地,我们要从小到大考虑 \(a,b\) 中的每一个位置 \(pos\)(注意这里的位置指的是排名,因为前面用 \(rk_a,rk_b\) 替换了 \(a,b\)),求出在它前面的所有位置 \(p_i\ (p_i\leq pos)\)(注意这里可能取到等于号,因为 \(a,b\) 中可能有相同的位置)中,与它类型不同的(即若 \(pos\) 是 \(b\) 中的位置,则 \(p_i\) 应该是 \(a\) 中的)所有位置 \(+1\) 后与它的区间 \(ht\) 最小值之和:对 \(a,b\) 分别维护一个单调栈 \(A,B\)。先用 \(val=\min_{i=pre+1}^{pos} ht_i\) 更新两个单调栈 \(A,B\)(\(pre\) 是上一次考虑的 \(pos\)),如果 \(pre=pos\) 则用 \(val=n-sa_{pos}+1\) 更新,需要注意的是这里的更新不是将一个数压入单调栈 \(A\) 或 \(B\),因为这个数是不算贡献的(如果算贡献,会导致计算了同属于 \(a\) 或同属于 \(b\) 的两个位置之间的重复贡献),相当于我们压入了一个宽为 \(0\),高为 \(val\) 的矩形;然后,若当前位置属于 \(a\),则计算单调栈 \(B\) 中的 “矩形面积和”,否则计算 \(A\) 中的矩形面积和;最后,若当前位置属于 \(a\),将 \(n-sa_{pos}+1\) 压入单调栈 \(A\),否则将其压入 \(B\),相当于我们压入了一个宽为 \(1\),高为 \(n-sa_{pos}+1\) 的矩形。所有计算出的 “矩形面积和” 之和即为答案。

时间复杂度 \(\mathcal{O}(n\log n+\sum k\log\sum k+\sum l\log \sum l)\)(后面的 \(\log\) 是排序所需的 \(\log\))。

CF1073G 代码
/*
Powered by C++11.
Author : Alex_Wei.
*/ #include <bits/stdc++.h>
using namespace std; #define ll long long const int N=2e5+5;
const int K=18; struct MonotoneStack{
ll stc[N],l[N],top,sum;
void modify(int val){
int len=0;
while(top&&stc[top]>=val)sum-=stc[top]*l[top],len+=l[top--];
sum+=len*val,stc[++top]=val,l[top]=len;
} void push(int val){
stc[++top]=val,l[top]=1,sum+=val;
}
}ta,tb; int n,q,k,l,a[N],b[N];
ll sta[N],stb[N];
char s[N];
struct SA{
int sa[N],rk[N<<1],ork[N<<1],ht[N];
int buc[N],id[N],px[N],mi[N][K];
bool cmp(int a,int b,int w){
return ork[a]==ork[b]&&ork[a+w]==ork[b+w];
} void build(){
int m=1<<7,p=0;
for(int i=1;i<=n;i++)buc[rk[i]=s[i]]++;
for(int i=1;i<=m;i++)buc[i]+=buc[i-1];
for(int i=n;i;i--)sa[buc[rk[i]]--]=i;
for(int w=1;w<=n;w<<=1,m=p,p=0){
for(int i=n;i>n-w;i--)id[++p]=i;
for(int i=1;i<=n;i++)if(sa[i]>w)id[++p]=sa[i]-w;
for(int i=0;i<=m;i++)buc[i]=0;
for(int i=1;i<=n;i++)buc[px[i]=rk[id[i]]]++;
for(int i=1;i<=m;i++)buc[i]+=buc[i-1];
for(int i=n;i;i--)sa[buc[px[i]]--]=id[i];
for(int i=1;i<=n;i++)ork[i]=rk[i]; p=0;
for(int i=1;i<=n;i++)rk[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p;
} for(int i=1,k=0;i<=n;i++){
if(k)k--;
while(s[i+k]==s[sa[rk[i]-1]+k])k++;
ht[rk[i]]=k;
} for(int j=0;j<K;j++)
for(int i=1;i<=n;i++)
if(j)mi[i][j]=min(mi[i][j-1],mi[i+(1<<j-1)][j-1]);
else mi[i][j]=ht[i];
} int query(int l,int r){
if(l>r)swap(l,r);
if(l==r)return n-sa[l]+1;
if(l+1==r)return ht[r];
int d=log2(r-(l++));
return min(mi[l][d],mi[r-(1<<d)+1][d]);
} ll run(ll k,ll l){
for(int i=1;i<=k;i++)a[i]=rk[a[i]];
for(int i=1;i<=l;i++)b[i]=rk[b[i]];
sort(a+1,a+k+1),sort(b+1,b+l+1);
ll lp=1,rp=1,ans=0,pre=0;
while(lp<=k||rp<=l){
int tp,pos;
if(lp>k||rp<=l&&b[rp]<a[lp])tp=2,pos=b[rp++];
else tp=1,pos=a[lp++];
int val=query(pre,pos);
ta.modify(val),tb.modify(val);
if(tp==1)ans+=tb.sum,ta.push(n-sa[pos]+1);
else ans+=ta.sum,tb.push(n-sa[pos]+1);
pre=pos;
} return ans;
}
}sa; int main(){
scanf("%d%d%s",&n,&q,s+1),sa.build();
while(q--){
scanf("%d%d",&k,&l);
for(int i=1;i<=k;i++)scanf("%d",&a[i]);
for(int i=1;i<=l;i++)scanf("%d",&b[i]);
cout<<sa.run(k,l)<<endl;
ta.top=tb.top=ta.sum=tb.sum=0;
}
return 0;
}

CF1073G Yet Another LCP Problem的更多相关文章

  1. cf1073G Yet Another LCP Problem (SA+权值线段树)

    反正先求一遍sa 然后这个问题可以稍微转化一下 默认比较A.B数组中元素的大小都是比较它们rank的大小,毕竟两个位置的LCP就是它们rank的rmq 然后每次只要求B[j]>=A[i]的LCP ...

  2. CF1073G Yet Another LCP Problem 后缀自动机 + 虚树 + 树形DP

    题目描述 记 $lcp(i,j)$ 表示 $i$ 表示 $i$ 这个后缀和 $j$ 这个后缀的最长公共后缀长度给定一个字符串,每次询问的时候给出两个正整数集合 $A$ 和 $B$,求$\sum_{i\ ...

  3. Educational Codeforces Round 53 (Rated for Div. 2)G. Yet Another LCP Problem

    题意:给串s,每次询问k个数a,l个数b,问a和b作为后缀的lcp的综合 题解:和bzoj3879类似,反向sam日神仙...lcp就是fail树上的lca.把点抠出来建虚树,然后在上面dp即可.(感 ...

  4. Codeforces 1073G Yet Another LCP Problem $SA$+单调栈

    题意 给出一个字符串\(s\)和\(q\)个询问. 每次询问给出两个长度分别为\(k,l\)的序列\(a\)和序列\(b\). 求\(\sum_{i=1}^{k}\sum_{j=1}^{l}lcp(s ...

  5. 虚树总结&题单&简要题解

    简介 虚树,即剔除所有无关结点,只保留询问点和询问点的相关结点(两两之间的LCA),建一棵新树,这棵新树就是虚树.通过虚树,可以有效的减小询问(甚至修改)的复杂度.设询问点的个数是\(k\),那么建虚 ...

  6. SAM 做题笔记(各种技巧,持续更新,SA)

    SAM 感性瞎扯. 这里是 SAM 做题笔记. 本来是在一篇随笔里面,然后 Latex 太多加载不过来就分成了两篇. 标 * 的是推荐一做的题目. trick 是我总结的技巧. I. P3804 [模 ...

  7. Codeforces-Educational Codeforces Round 53题解

    写之前,先发表下感慨:好久没写题解了,也许是因为自己越来越急利了,也可以说是因为越来越懒了. A. Diverse Substring 直接找一找有没有相邻的两个不同的字符即可. B. Vasya a ...

  8. Mediocre String Problem (2018南京M,回文+LCP 3×3=9种做法 %%%千年好题 感谢"Grunt"大佬的细心讲解)

    layout: post title: Mediocre String Problem (2018南京M,回文+LCP 3×3=9种做法 %%%千年好题 感谢"Grunt"大佬的细 ...

  9. [CF1073G]LCP问题

    题意:给一个长n的字符串S,q组询问,每组给两个集合A,B.求集合A中的点和集合B中的点所有组合情况的lcp的和. 思路: 好像比较常规,可是代码能力差还是调了1.5h.主要还是虚树板子不熟(加入的时 ...

随机推荐

  1. 整理一下在 npmjs.com 上面发布资源包踩过的坑

    正常流程就不说了,网上有很多,比如写代码.打包.注册.登录.发布等. 邮箱要激活 在 npmjs.com 上面注册账号的时候需要填写邮箱,然后登录网址的时候并没有强制要求你去邮箱激活. 但是到了发布资 ...

  2. Java:ConcurrentHashMap类小记-3(JDK8)

    Java:ConcurrentHashMap类小记-3(JDK8) 结构说明 // 所有数据都存在table中, 只有当第一次插入时才会被加载,扩容时总是以2的倍数进行 transient volat ...

  3. STM32中按键中断分析

    在按键学习中,我们有用到查询的方法来判断按键事件是否发生,这种查询按键事件适用于程序工作量较少的情况下,一旦程序中工作量较大较多,则势必影响程序运行的效率,为了简化程序中控制的功能模块的执行时间,引入 ...

  4. python中yield的理解

    首先我要吐槽一下,看程序的过程中遇见了yield这个关键字,然后百度的时候,发现没有一个能简单的让我懂的,讲起来真TM的都是头头是道,什么参数,什么传递的,还口口声声说自己的教程是最简单的,最浅显易懂 ...

  5. longest-consecutive-sequence leetcode C++

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  6. hdu 5084 HeHe (观察思考题)

    题意: 给一个n行n列的矩阵M.这个矩阵M由2n-1数构成.分别是t1,t2,....t(2n-1). m个query.每个query形式:ri, ci. 第i个query的答案 ans[i]=E[( ...

  7. 在纯JaveScript中实现报表导出:从“PDF”到“JPG”

    我们在前端报表中完成了各种工作数据的输入或内容处理之后,需要做什么? 数据的导出! 这些数据的常用导出格式有:PDF.Excel.HTML和图片几大类型. 但总有一些实际应用场景,需要的不仅仅是将现有 ...

  8. Typecho部署小破站

    写在前面 以前利用 Github Page + Hexo框架 + Next主题搭建过静态博客,没错就是那个黑白色系的网页!但是体验并不是很好,一来本身是静态网页,页面内容要修改都需要在本地修改完上传到 ...

  9. Linux 兴趣小组2016免试题 第四关揭秘

    Linux 兴趣小组2016免试题 点这里 首先贴出第四关链接Linux 兴趣小组2016免试题 第四关 第四关: 进入网址我们看到的是4张扑克牌K,这是什么意思? 要我斗地主?好了,还是乖乖的先查看 ...

  10. k8s入坑之路(4)kubenetes安装

    三种安装方法: 1.kubeadm 2.kubespray 3.二进制安装 kubespray安装kubernetes集群 优点: 1.kuberspray对比kubeadm更加简洁内部集成了kube ...