反正先求一遍sa

然后这个问题可以稍微转化一下

默认比较A、B数组中元素的大小都是比较它们rank的大小,毕竟两个位置的LCP就是它们rank的rmq

然后每次只要求B[j]>=A[i]的LCP(B[j],A[i]),然后再求A[j]>B[i]的LCP(A[j],B[i])即可

这两个其实是差不多的,下面只说B[j]>=A[i]的怎么算

排序以后从后往前推着做(当然从前往后也行)

用一个权值线段树记下来LCP(A[i],B[j])==x的B[j]的数量、以及这个数量*x的和

然后考虑怎么把它从A[i]转移到A[i-1]

其实就是对于每个j给LCP(A[i],B[j])和LCP(A[i-1],A[i])取个min,放到权值线段树上,就是把大于LCP(A[i-1],A[i])的都删掉,然后在LCP(A[i-1],A[i])处加上刚才删掉的个数

所以我推着做的时候,先来取个min,然后把新来的B[j]加到线段树里,每做一个A[i]统计一下线段树整体的和即可

 #include<bits/stdc++.h>
#define pa pair<int,int>
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=4e5+; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N,M,Q;
char s[maxn];
int sa[maxn],rnk[maxn],hei[maxn],rank1[maxn],tmp[maxn],cnt[maxn];
int st[maxn][]; inline void getsa(){
int i,j=,k;
for(i=;i<=N;i++) cnt[s[i]]=;
for(i=;i<=M;i++) cnt[i]+=cnt[i-];
for(i=N;i;i--) rnk[i]=cnt[s[i]]; for(k=;j!=N;k<<=){
memset(cnt,,sizeof(cnt));
for(i=;i<=N;i++) cnt[rnk[i+k>N?:i+k]]++;
for(i=;i<=M;i++) cnt[i]+=cnt[i-];
for(i=N;i;i--) tmp[cnt[rnk[i+k>N?:i+k]]--]=i;
memset(cnt,,sizeof(cnt));
for(i=;i<=N;i++) cnt[rnk[i]]++;
for(i=;i<=M;i++) cnt[i]+=cnt[i-];
for(i=N;i;i--) sa[cnt[rnk[tmp[i]]]--]=tmp[i];
memcpy(rank1,rnk,sizeof(rank1));
rnk[sa[]]=j=;
for(i=;i<=N;i++){
if(rank1[sa[i]]!=rank1[sa[i-]]||rank1[sa[i]+k>N?:sa[i]+k]!=rank1[sa[i-]+k>N?:sa[i-]+k]) j++;
rnk[sa[i]]=j;
}M=j;
}
for(i=;i<=N;i++) sa[rnk[i]]=i;
} inline void geth(){
for(int i=,j=;i<=N;i++){
if(rnk[i]==) continue;
if(j) j--;
int x=sa[rnk[i]-];
while(x+j<=N&&i+j<=N&&s[x+j]==s[i+j]) j++;
hei[rnk[i]]=j;
}
} inline void getst(){
for(int i=N;i;i--){
st[i][]=hei[i];
for(int j=;st[i+(<<(j-))][j-];j++){
st[i][j]=min(st[i][j-],st[i+(<<(j-))][j-]);
}
}
} inline int rmq(int l,int r){
if(l>r) return N-sa[r]+;
int x=log2(r-l+);
return min(st[l][x],st[r-(<<x)+][x]);
} ll sum[maxn<<],siz[maxn<<];
bool laz[maxn<<]; inline void update(int p){sum[p]=sum[p<<]+sum[p<<|],siz[p]=siz[p<<]+siz[p<<|];}
inline void pushdown(int p){
if(!laz[p]) return;
int a=p<<,b=p<<|;
sum[a]=siz[a]=,laz[a]=;
sum[b]=siz[b]=,laz[b]=;
laz[p]=;
}
int erase(int p,int l,int r,int x,int y){
if(x<=l&&r<=y){
int re=siz[p];
siz[p]=sum[p]=;laz[p]=;
pushdown(p);
return re;
}else{
pushdown(p);
int m=l+r>>,re=;
if(x<=m) re=erase(p<<,l,m,x,y);
if(y>=m+) re+=erase(p<<|,m+,r,x,y);
update(p);
return re;
}
}
void add(int p,int l,int r,int x,int y){
if(l==r){
siz[p]+=y,sum[p]+=1ll*y*l;
}else{
pushdown(p);
int m=l+r>>;
if(x<=m) add(p<<,l,m,x,y);
else add(p<<|,m+,r,x,y);
update(p);
}
} inline bool cmp(int a,int b){return rnk[a]<rnk[b];} int A[maxn],B[maxn];
ll solve(int k,int l){
sort(A+,A+k+,cmp);sort(B+,B+l+,cmp);
ll re=;
for(int i=k,j=l;i;i--){
if(i!=k){
int x=rmq(rnk[A[i]]+,rnk[A[i+]]),t=erase(,,N,x+,N);
add(,,N,x,t);
}
for(;rnk[B[j]]>=rnk[A[i]]&&j;j--)
add(,,N,rmq(rnk[A[i]]+,rnk[B[j]]),);
re+=sum[];
}
erase(,,N,,N);
for(int i=k,j=l;j;j--){
if(j!=l){
int x=rmq(rnk[B[j]]+,rnk[B[j+]]),t=erase(,,N,x+,N);
add(,,N,x,t);
}
for(;rnk[A[i]]>rnk[B[j]]&&i;i--)
add(,,N,rmq(rnk[B[j]]+,rnk[A[i]]),);
re+=sum[];
}
erase(,,N,,N);
return re;
} int main(){
//freopen(".in","r",stdin);
int i,j,k;
N=rd(),Q=rd();
scanf("%s",s+);
M=;
getsa();geth();getst();
for(i=;i<=Q;i++){
int a=rd(),b=rd();
for(j=;j<=a;j++)
A[j]=rd();
for(j=;j<=b;j++)
B[j]=rd();
printf("%I64d\n",solve(a,b));
}
return ;
}

cf1073G Yet Another LCP Problem (SA+权值线段树)的更多相关文章

  1. BZOJ4627 前缀和 + 权值线段树

    https://www.lydsy.com/JudgeOnline/problem.php?id=4627 题意:求序列中和在L到R之间的字串种数. 要求的是和的范围,我们可以考虑先求一个前缀和pre ...

  2. F - 回转寿司 (权值线段树)

    题目链接:https://cn.vjudge.net/contest/281960#problem/F 题目大意:中文题目 具体思路:权值线段树,我们每次寻找的是满足 (i<j)   L< ...

  3. BZOJ 4605 崂山白花蛇草水(权值线段树+KD树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4605 [题目大意] 操作 1 x y k 表示在点(x,y)上放置k个物品, 操作 2 ...

  4. HDU 6464 免费送气球 【权值线段树】(广东工业大学第十四届程序设计竞赛)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6464 免费送气球 Time Limit: 2000/1000 MS (Java/Others)    M ...

  5. hdu 5592 ZYB's Premutation (权值线段树)

    最近在线段树的世界里遨游,什么都能用线段树做,这不又一道权值线段树了么. ZYB's Premutation Time Limit: 2000/1000 MS (Java/Others)    Mem ...

  6. [bzoj 2733]启发式合并权值线段树

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2733 平衡树待学习.从一个博客学到了合并权值线段树的姿势:http://blog.csdn ...

  7. HDU 6464 权值线段树 && HDU 6468 思维题

    免费送气球 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submi ...

  8. D. Restore Permutation(权值线段树)

    D. Restore Permutation time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  9. HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)

    layout: post title: HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并) author: "luowentaoaa&quo ...

随机推荐

  1. 企业级分布式应用服务EDAS _Dubbo商业版_微服务PaaS平台 【EDAS Serverless 运维 创业】

    企业级分布式应用服务EDAS _Dubbo商业版_微服务PaaS平台_分布式框架 - 阿里云https://www.aliyun.com/product/edas?source_type=yqzb_e ...

  2. 配置nginx反向代理服务器,解决浏览器跨域调用接口的限制问题

    配置nginx反向代理服务器,解决浏览器跨域调用接口的限制问题 - 大venn的博客 - CSDN博客https://blog.csdn.net/u011135260/article/details/ ...

  3. Ubuntu 12.04 安装socks5代理服务器dante-server

    dante-server是一个很好的socks4/5代理服务器软件. 使用apt-get安装   1 apt-getinstall dante-server 添加一个用户   1 2 useradd ...

  4. node exprss-session 和connect-mongo

    let express = require('express'); let session = require('express-session'); let app = new express(); ...

  5. python与C,在写程序时踩过的坑!

    1.  python与C有很多相似之处, 其一就是指针的大量应用,  因此在使用临时变量保存数据, 并将临时变量传递给其他变量时需要创建内存; 例如,在C中, char *temp 每次获取到不同的字 ...

  6. mybatis出现NoSuchMethodException异常

    今天在idea中调试项目(ssm搭建的项目)的时候,mybatis突然出现了NoSuchMethodException异常,具体的异常时: java.lang.NoSuchMethodExceptio ...

  7. How to execute a Stored Procedure with Entity Framework Code First

    Recently I worked on a project, which I started as code first and then I forced to switch to Databas ...

  8. UVA 12171 Sculpture

    https://vjudge.net/problem/UVA-12171 题目 某人设计雕塑,用的是很扯的方法:把一堆长方体拼起来.给出长方体的坐标和长宽高,求外表面积.因为要将这雕塑进行酸洗,需要知 ...

  9. Java常用调试技巧(转)

    调试不仅可以查找到应用程序缺陷所在,还可以解决缺陷.对于Java程序员来说,他们不仅要学会如何在Eclipse里面开发像样的程序,更需要学会如何调试程序.本文介绍了Java程序员必知的10个调试技巧, ...

  10. 使用Promise解决多层异步调用的简单学习【转】

    前言 本文章转载文章: https://www.jianshu.com/p/29da9aef4c1c 第一次接触到Promise这个东西,是2012年微软发布Windows8操作系统后抱着作死好奇的心 ...