题意

给出一个字符串\(s\)和\(q\)个询问。

每次询问给出两个长度分别为\(k,l\)的序列\(a\)和序列\(b\)。

求\(\sum_{i=1}^{k}\sum_{j=1}^{l}lcp(s[a_i…n],s[b_j…n])\)

Solution

\(SA\)练习题。

求出\(height\)数组后,每次询问相当于询问\(l*k\)个区间\(min\)之和。

岂不单调栈?

对没错,这个题解就是提供给你代码对拍的

#include<bits/stdc++.h>
#define For(i,x,y) for (register int i=(x);i<=(y);i++)
#define Dow(i,x,y) for (register int i=(x);i>=(y);i--)
#define cross(i,k) for (register int i=first[k];i;i=last[i])
using namespace std;
typedef long long ll;
inline ll read(){
ll x=0;int ch=getchar(),f=1;
while (!isdigit(ch)&&(ch!='-')&&(ch!=EOF)) ch=getchar();
if (ch=='-'){f=-1;ch=getchar();}
while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int N = 2e5+10;
int n,Q,l[N],k[N];
char s[N];
int SA[N],height[N],rk[N],cnt[N],x[N],y[N];
inline void RadixSort(){
int Max=0;
For(i,1,n) cnt[x[i]]++,Max=max(Max,x[i]);
For(i,1,Max) cnt[i]+=cnt[i-1];
Dow(i,n,1) SA[cnt[x[y[i]]]--]=y[i];
For(i,1,Max) cnt[i]=0;
}
inline void GetSA(){
For(i,1,n) x[i]=s[i],y[i]=i;
RadixSort();
for (int i=1,p;p<n;i<<=1){
p=0;
For(j,n-i+1,n) y[++p]=j;
For(j,1,n) if (SA[j]>i) y[++p]=SA[j]-i;
RadixSort(),swap(x,y),x[SA[1]]=p=1;
For(j,2,n) x[SA[j]]=(y[SA[j]]==y[SA[j-1]]&&y[SA[j]+i]==y[SA[j-1]+i])?p:++p;
}
For(i,1,n) rk[SA[i]]=i;
int now=0;
For(i,1,n){
if (rk[i]==1) continue;now=max(now-1,0);
for (int j=SA[rk[i]-1];j+now<=n&&i+now<=n&&s[j+now]==s[i+now];now++);
height[rk[i]]=now;
}
}
int Min[N][20],Log[N];
inline void init(){
For(i,1,n) Log[i]=log(i)/log(2);
For(i,1,n) Min[i][0]=height[i];
For(j,1,Log[n]) For(i,1,n-(1<<j)+1) Min[i][j]=min(Min[i][j-1],Min[i+(1<<j-1)][j-1]);
}
inline int Query(int l,int r){
int L=Log[r-l+1];
return min(Min[l][L],Min[r-(1<<L)+1][L]);
}
struct node{
int x,y;
}a[N<<1];
inline bool cmp(node a,node b){return a.x==b.x?a.y<b.y:a.x<b.x;}
int top,q[N<<1],c[N<<1];
ll Sum,ans;
inline void solve(int m,int M){
int cnt=0;
For(i,1,M) a[++cnt]=(node){rk[read()],1};
For(i,1,m) a[++cnt]=(node){rk[read()],0};
sort(a+1,a+1+cnt,cmp),ans=top=Sum=0;
a[cnt+1]=(node){-1,0};
int r=cnt;while (a[r].y==1) r--;
Dow(i,r,1){
if (i!=r){
int x=Query(a[i].x+1,a[i+1].x),s=a[i+1].y^1;
while (x<=q[top]&&top) Sum-=c[top]*q[top],s+=c[top--];
q[++top]=x,c[top]=s,Sum+=1ll*s*x;
}
if (a[i].y) ans+=Sum;
else if (a[i+1].x==a[i].x) ans+=n-SA[a[i].x]+1;
}
For(i,2,cnt) if (a[i].x==a[i-1].x) swap(a[i],a[i-1]);
top=Sum=0;
r=1;while (a[r].y==1) r++;
For(i,r,cnt){
if (i!=r){
int x=Query(a[i-1].x+1,a[i].x),s=a[i-1].y^1;
while (x<=q[top]&&top) Sum-=c[top]*q[top],s+=c[top--];
q[++top]=x,c[top]=s,Sum+=1ll*s*x;
}
if (a[i].y) ans+=Sum;
}
}
ll Ans[N];
int main(){
n=read(),Q=read(),scanf("%s",s+1);
GetSA(),init();
For(i,1,Q) solve(read(),read()),Ans[i]=ans;
For(i,1,Q) printf("%lld\n",Ans[i]);
}

Codeforces 1073G Yet Another LCP Problem $SA$+单调栈的更多相关文章

  1. Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)

    原文链接https://www.cnblogs.com/zhouzhendong/p/9256033.html 题目传送门 - CF873F 题意 给定长度为 $n$ 的字符串 $s$,以及给定这个字 ...

  2. Codeforces 1156E Special Segments of Permutation(单调栈)

    可以用单调栈直接维护出ai所能覆盖到的最大的左右范围是什么,然后我们可以用这个范围暴力的去查询这个区间的是否有满足的点对,一个小坑点,要对左右区间的大小进行判断,只需要去枚举距离i最近的一段区间去枚举 ...

  3. Codeforces Round #622 (Div. 2)C(单调栈,DP)

    构造出的结果一定是一个单峰/\这种样子的 #define HAVE_STRUCT_TIMESPEC #include<bits/stdc++.h> using namespace std; ...

  4. Codeforces Round #305 (Div. 2) D 维护单调栈

    D. Mike and Feet time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  5. Codeforces 1107G Vasya and Maximum Profit 线段树最大子段和 + 单调栈

    Codeforces 1107G 线段树最大子段和 + 单调栈 G. Vasya and Maximum Profit Description: Vasya got really tired of t ...

  6. Codeforces 802I Fake News (hard) (SA+单调栈) 或 SAM

    原文链接http://www.cnblogs.com/zhouzhendong/p/9026184.html 题目传送门 - Codeforces 802I 题意 求一个串中,所有本质不同子串的出现次 ...

  7. CodeForces 548D 单调栈

    Mike and Feet Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Subm ...

  8. Codeforces 1107G Vasya and Maximum Profit [单调栈]

    洛谷 Codeforces 我竟然能在有生之年踩标算. 思路 首先考虑暴力:枚举左右端点直接计算. 考虑记录\(sum_x=\sum_{i=1}^x c_i\),设选\([l,r]\)时那个奇怪东西的 ...

  9. Codeforces Round #541 (Div. 2) G dp + 思维 + 单调栈 or 链表 (连锁反应)

    https://codeforces.com/contest/1131/problem/G 题意 给你一排m个的骨牌(m<=1e7),每块之间相距1,每块高h[i],推倒代价c[i],假如\(a ...

随机推荐

  1. 在JS数组指定位置插入元素

    很多与数组有关的任务听起来很简单,但实际情况并不总是如此,而开发人员在很多时候也用不到他.最近我碰到了这样一个需求: 将一个元素插入到现有数组的特定索引处.听起来很容易和常见,但需要一点时间来研究它. ...

  2. 【bzoj题解】2186 莎拉公主的困惑

    题目传送门. 题意:求\([1,n!]\)中与\(m!\)互质的数的个数,对质数\(R\)取模,\(n\geq m\). 答案应该等于\(\frac{n!}{m!}\phi(m!)=\frac{n!} ...

  3. 2017-2018-2 20179205《网络攻防技术与实践》第十一周作业 SQL注入攻击与实践

    <网络攻防技术与实践>第十一周作业 SQL注入攻击与实践 1.研究缓冲区溢出的原理,至少针对两种数据库进行差异化研究 缓冲区溢出原理   在计算机内部,输入数据通常被存放在一个临时空间内, ...

  4. 【LinuxC】GCC编译C程序,关闭随机基址

    1.编译.链接和运行程序 C代码示例: #include <stdio.h> #include <stdlib.h> int main() { printf("hel ...

  5. iBt(001-004)原文与试译

    Unit 001 Basic building materials include: timber, mud, stone, marble, brick, tile, steel, and cemen ...

  6. Ubuntu_安装Wiz笔记

    前言 安装完成了Linux,有了搜狗输入法,我们还需要笔记软件,本文主要介绍如何安装为知笔记 安装步骤 找到wiz官网:http://www.wiz.cn/ 获取Linux安装教程 安装QT 下载的Q ...

  7. Python基础:获取平台相关信息

    Windows 10家庭中文版,Python 3.6.4, 本文介绍了使用os.platform.sys三个模块获取Python程序的运行平台相关的信息. os模块:提供 各种各样的操作系统接口 os ...

  8. 缓存数据库-redis(管道)

    一:Redis 管道技术 Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务.这意味着通常情况下一个请求会遵循以下步骤: 客户端向服务端发送一个查询请求,并监听Socket返回,通常 ...

  9. 可怕的线程上下文类装载器(TCCL)

    在明天的 OSGi 2012 社区活动上,我将以"如何使你的类库在不依赖 OSGi 的情况下进行友好地 OSGi"为主题进行演讲.在演讲中我将会提及 Java 的线程上下文类加载器 ...

  10. sql server 2000系统表sysproperties在SQL 2008中无效的问题

    Sqlserver有一个扩展属性系统表sysproperties,因为只接触过MSSQL2005及以后的版本,在生产库2008版本及联机文档上搜了下都找不到这个系统表,后来发现这个系统表在2005版本 ...