2022.02.20 SA

如果我还能看见明天黎明,如果我还能再爬起来,我仍会走我的路,哪怕这条路已经荒废许久,也许我们无法拥有感情,我们甚至无法像个正常人一样接受太阳的洗礼,但是我依然会执行我的条约,哪怕不会有人记得我,哪怕我们并不会记入编年史,我们的名字也许会成为辱骂的对象,我依然执行我的信条当其他人都盲目追寻真理的时候,记住,万事皆虚,当其他人的思想都被法律与道德所束缚的时候,记住,万事皆允。 我们躬耕于黑暗却服侍于,并非是我选择了这样的一生,而是一生选了我。——《刺客信条》

SA:

http://www.yhzq-blog.cc/后缀数组算法总结/

段错误:

https://blog.csdn.net/lotluck/article/details/42948593

https://www.cnblogs.com/smalltigerlee/archive/2011/10/26/2225183.html

Step 1 模板代码

1.1 前置知识 基数排序

https://www.cnblogs.com/Cherish486/p/15394442.html

1.2 代码如下(SA模板1.0)

https://www.luogu.com.cn/problem/P4248

#include<bits/stdc++.h>
using namespace std; #define Ri register
const int N=5e5+10;
typedef long long ll;
int n,m,wa[N],wb[N],wv[N],wsi[N],sa[N],ranki[N],r[N];
int height[N],h[N];
int stacki[N],top;
char s[N];
ll ans[N]; inline int cmp(int *r,int a,int b,int len){
return r[a]==r[b]&&r[a+len]==r[b+len];
}
inline void SA(int *r,int *sa,int n,int m){
m=129;
int *x=wa,*y=wb,*t;
for(Ri int i=0;i<m;i++)wsi[i]=0;
for(Ri int i=0;i<n;i++)++wsi[x[i]=r[i]];
for(Ri int i=1;i<m;i++)wsi[i]+=wsi[i-1];
for(Ri int i=n-1;~i;i--)sa[--wsi[x[i]]]=i;
/*cout<<"r "<<endl;
for(Ri int i=0;i<n;i++)cout<<r[i]<<" ";cout<<endl;
cout<<"x "<<endl;
for(Ri int i=0;i<n;i++)cout<<x[i]<<" ";cout<<endl;
cout<<"sa "<<endl;
for(Ri int i=0;i<n;i++)cout<<sa[i]<<" ";cout<<endl;*/
int p=1;
for(Ri int j=1;p<n;j*=2,m=p){
//cout<<"len j "<<j<<endl;
p=0;
for(Ri int i=n-j;i<n;i++)y[p++]=i;
for(Ri int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
//这里是按照第一次sa数组的排序,然后记录它前一个的位置,这样就是对suf第二个字符进行排序
//y中存第二个关键词排序后的结果
/*cout<<"sa "<<endl;
for(Ri int i=0;i<n;i++)cout<<sa[i]<<" ";cout<<endl;
cout<<"x "<<endl;
for(Ri int i=0;i<n;i++)cout<<x[i]<<" ";cout<<endl;
cout<<"y "<<endl;
for(Ri int i=0;i<p;i++)cout<<y[i]<<" ";cout<<endl;*/
for(Ri int i=0;i<n;i++)wv[i]=x[y[i]];
//根据第二关键词更新了第一关键词的顺序,就是根据第二关键词,找第一关键词
//x中存第一关键词排序的顺序
/*cout<<"wv "<<endl;
for(Ri int i=0;i<n;i++)cout<<wv[i]<<" ";cout<<endl;*/
for(Ri int i=0;i<m;i++)wsi[i]=0;
for(Ri int i=0;i<n;i++)++wsi[wv[i]];
for(Ri int i=1;i<m;i++)wsi[i]+=wsi[i-1];
for(Ri int i=n-1;~i;i--)sa[--wsi[wv[i]]]=y[i];
//y中存的是W位置,sa中需要存的就是位置
/*cout<<"sa "<<endl;
for(Ri int i=0;i<n;i++)cout<<sa[i]<<" ";cout<<endl;*/
t=x,x=y,y=t;
p=1;
x[sa[0]]=0;
for(Ri int i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
//x是两个关键词排序后的新序号
/*cout<<"x before y ranki "<<endl;
for(Ri int i=0;i<n;i++)cout<<x[i]<<" ";cout<<endl;*/
}
}
inline void find_height(int *r,int *sa,int n){
int k=0,j;
for(Ri int i=1;i<n;i++)ranki[sa[i]]=i;
/*cout<<"ranki "<<endl;
for(Ri int i=0;i<n;i++)cout<<ranki[i]<<" ";cout<<endl;*/
for(Ri int i=0;i<n-1;height[ranki[i++]]=k)
for(k?k--:0,j=sa[ranki[i]-1];r[i+k]==r[j+k];k++);
/*cout<<"height "<<endl;
for(Ri int i=0;i<n;i++)cout<<height[i]<<" ";cout<<endl;*/
} signed main(){
scanf("%s",s);
n=strlen(s);
ll fin=1ll*n*(n+1)*(n-1)/2;
for(Ri int i=0;i<n;i++)r[i]=s[i];
r[n++]=0;
SA(r,sa,n,m);
find_height(r,sa,n);
for(Ri int i=0;i<n;i++){
while(top&&height[i]<height[stacki[top]])--top;
int j=stacki[top];
ans[i]=ans[j]+1ll*(i-j)*height[i];
fin-=2*ans[i];
stacki[++top]=i;
}
cout<<fin;
return 0;
}

1.3 重点

1.3.1 关于判断越界

有两种方法:

  1. 手动判断越界

    inline int cmp(int *r,int a,int b,int len){
    return r[a]==r[b]&&
    (a+len>=n?-1:r[a+len])==(b+len>=n?-1:r[b+len]);
    }
  2. 字符串末尾加0表示结束

    r[n++]=0;

Step 2 练习题

P2178 [NOI2015] 品酒大会

https://www.luogu.com.cn/problem/P2178

https://www.cnblogs.com/refun/p/8679198.html

100pts(别人的)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define MAXN (300000+100)
using namespace std;
int wt[MAXN],wa[MAXN],wb[MAXN];
int SA[MAXN],Rank[MAXN],Height[MAXN];
char r[MAXN];
int a[MAXN],cnt;
int ID[MAXN],Father[MAXN];
long long Size[MAXN],Max[MAXN],Min[MAXN],Ans[MAXN][2],INF;
int n,m=130; bool cmp(int *y,int a,int b,int k)
{
int arank1=y[a];
int brank1=y[b];
int arank2=a+k>=n?-1:y[a+k];
int brank2=b+k>=n?-1:y[b+k];
return arank1==brank1 && arank2==brank2;
} void Build_SA()
{
int *x=wa,*y=wb;
for (int i=0;i<m;++i) wt[i]=0;
for (int i=0;i<n;++i) wt[x[i]=r[i]]++;
for (int i=1;i<m;++i) wt[i]+=wt[i-1];
for (int i=n-1;i>=0;--i) SA[--wt[x[i]]]=i; for (int j=1;j<=n;j<<=1)
{
int p=0;
for (int i=n-j;i<n;++i) y[p++]=i;
for (int i=0;i<n;++i) if (SA[i]>=j) y[p++]=SA[i]-j; for (int i=0;i<m;++i) wt[i]=0;
for (int i=0;i<n;++i) wt[x[y[i]]]++;
for (int i=1;i<m;++i) wt[i]+=wt[i-1];
for (int i=n-1;i>=0;--i) SA[--wt[x[y[i]]]]=y[i]; m=1;swap(x,y);
x[SA[0]]=0;
for (int i=1;i<n;++i)
x[SA[i]]=cmp(y,SA[i],SA[i-1],j)?m-1:m++;
if (m>=n) break;
}
} void Build_Height()
{
for (int i=0;i<n;++i) Rank[SA[i]]=i;
int k=0;
Height[0]=0;
for (int i=0;i<n;++i)
{
if (!Rank[i]) continue;
if (k) k--;
int j=SA[Rank[i]-1];
while (r[i+k]==r[j+k]) k++;
Height[Rank[i]]=k;
}
} int Find (int x) {return Father[x]==x?x:Father[x]=Find(Father[x]);}
void Merge (int x,int y)
{
int f1=Find(x),f2=Find(y); int k=Height[x];
Ans[k][0]+=Size[f2]*Size[f1];
Ans[k][1]=max(max(Max[f2]*Max[f1],Min[f2]*Min[f1]),Ans[k][1]); Min[f1]=min(Min[f1],Min[f2]);
Max[f1]=max(Max[f1],Max[f2]);
Father[f2]=f1;
Size[f1]+=Size[f2];
} void Solve()
{
for (int i=0;i<n;++i)
{
Father[i]=i;
Size[i]=1;
Max[i]=Min[i]=a[SA[i]];
}
for (int i=0;i<=n-1;++i)
if (Find(ID[i])!=Find(ID[i]-1))
Merge(ID[i],ID[i]-1);
} bool cmp1(int x,int y)
{
return Height[x]>Height[y];
} int main()
{
memset(&INF,0x7f,sizeof(INF));
scanf("%d",&n);
scanf("%s",r);
for (int i=0;i<n;++i)
scanf("%d",&a[i]);
Build_SA();
Build_Height();
for (int i=0;i<n;++i)
{
ID[i]=i;
Ans[i][0]=0;
Ans[i][1]=-INF;
}
sort(ID,ID+n,cmp1);
Solve();
for (int i=n-2;i>=0;--i)
{
Ans[i][0]+=Ans[i+1][0];
Ans[i][1]=max(Ans[i][1],Ans[i+1][1]);
}
for (int i=0;i<n;++i)
printf("%lld %lld\n",Ans[i][0],Ans[i][0]==0?0:Ans[i][1]);
}

90pts(我的)

#include<bits/stdc++.h>
using namespace std; #define int long long
#define Ri register
const int N=3e6+1000;
const int inf=1e18;
int n,m,a[N];
int r[N],wa[N],wb[N],wv[N],t[N],sa[N],ranki[N];
int height[N];
int fa[N],sizei[N],maxn[N],minn[N],ans[N][2],id[N];
char s[N]; inline int cmp(int *r,int a,int b,int len){
return r[a]==r[b]&&r[a+len]==r[b+len];
}
inline void SA(int *r,int *sa,int n,int m){
m=400;
int *x=wa,*y=wb;
for(Ri int i=0;i<m;i++)t[i]=0;
for(Ri int i=0;i<n;i++)++t[x[i]=r[i]];
for(Ri int i=1;i<m;i++)t[i]+=t[i-1];
for(Ri int i=n-1;~i;i--)sa[--t[x[i]]]=i;
//cout<<"Case 1 "<<endl;
int p=1;
for(Ri int j=1;p<n&&j<=n;j<<=1,m=p){
p=0;
for(Ri int i=n-j;i<n;i++)y[p++]=i;
for(Ri int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
for(Ri int i=0;i<m;i++)t[i]=0;
for(Ri int i=0;i<n;i++)wv[i]=x[y[i]];
for(Ri int i=0;i<n;i++)++t[wv[i]];
for(Ri int i=1;i<m;i++)t[i]+=t[i-1];
for(Ri int i=n-1;~i;i--)sa[--t[wv[i]]]=y[i];
int *t;
t=x;x=y;y=t;
x[sa[0]]=0;
p=1;
for(Ri int i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
//for(Ri int i=0;i<n;i++)cout<<sa[i]<<endl;
}
inline void calc(int *r,int *sa,int n){
//cout<<"Case 2"<<endl;
int k=0,j;
for(Ri int i=0;i<n;i++)ranki[sa[i]]=i;
for(Ri int i=0;i<n;height[ranki[i++]]=k)//if(ranki[i])
for(k?--k:0,j=sa[ranki[i]-1];r[i+k]==r[j+k];++k);
/*cout<<"ranki "<<endl;
for(Ri int i=0;i<n;i++)cout<<ranki[i]<<" ";cout<<endl;
cout<<"height "<<endl;
for(Ri int i=0;i<n;i++)cout<<height[i]<<" ";cout<<endl;*/
//for(Ri int i=0;i<n;i++)cout<<sa[i]<<endl;
}
inline int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
inline void merge(int x,int y){
int xi=find(x),yi=find(y);
int k=height[x];
ans[k][0]+=sizei[xi]*sizei[yi];
ans[k][1]=max(ans[k][1],max(maxn[xi]*maxn[yi],minn[xi]*minn[yi]));
maxn[xi]=max(maxn[xi],maxn[yi]);
minn[xi]=min(minn[xi],minn[yi]);
fa[yi]=xi;
sizei[xi]+=sizei[yi];
}
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
inline int cmp1(int x,int y){
return height[x]>height[y];
} signed main(){
//freopen("P2178_3.in","r",stdin);
//freopen("P2178.out","w",stdout);
n=read();
//cout<<n<<endl;
scanf("%s",s);
for(Ri int i=0;i<n;i++)r[i]=s[i];
//r[n++]=0;
SA(r,sa,n,m);calc(r,sa,n);
//--n;
//cout<<"Case 3"<<endl;
for(Ri int i=0;i<n;i++){
a[i]=read();
id[i]=i;
ans[i][0]=0;
ans[i][1]=-inf;
}
sort(id,id+n,cmp1);
//cout<<"Case 4"<<endl;
//cout<<n<<endl;
for(Ri int i=0;i<n;i++)fa[i]=i,sizei[i]=1,minn[i]=maxn[i]=a[sa[i]];
//cout<<"Case 6"<<endl;
for(Ri int i=0;i<n;i++)if(find(id[i])!=find(id[i]-1)&&id[i]-1>-1)merge(id[i],id[i]-1);
//cout<<"Case 5"<<endl;
for(int i=n-2;i>=0;i--)ans[i][0]+=ans[i+1][0],ans[i][1]=max(ans[i][1],ans[i+1][1]);
for(Ri int i=0;i<n;i++)cout<<ans[i][0]<<" "<<(ans[i][0]==0?0:ans[i][1])<<endl;
return 0;
}

P4051 [JSOI2007]字符加密

https://www.luogu.com.cn/problem/P4051

100pts(标准求SA模板2.0)

#include<bits/stdc++.h>
using namespace std; #define Ri register
const int N=2e5+10;
int n,m,r[N],sa[N],wa[N],wb[N],wv[N],wt[N],ranki[N],height[N];
char s[N]; inline int cmp(int *r,int a,int b,int len){
return r[a]==r[b]&&r[a+len]==r[b+len];
}
inline void SA(int *r,int *sa,int n,int m){
m=400;
int *x=wa,*y=wb,*t,p=1;
for(Ri int i=0;i<m;i++)wt[i]=0;
for(Ri int i=0;i<n;i++)++wt[x[i]=r[i]];
for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1];
for(Ri int i=n-1;~i;i--)sa[--wt[x[i]]]=i;
for(Ri int j=1;j<=n;j<<=1,m=p){
//更改处:改为根据j和p共同判断是否跳出循环
p=0;
for(Ri int i=n-j;i<n;i++)y[p++]=i;
for(Ri int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
for(Ri int i=0;i<m;i++)wt[i]=0;
for(Ri int i=0;i<n;i++)wv[i]=x[y[i]];
for(Ri int i=0;i<n;i++)++wt[wv[i]];
for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1];
for(Ri int i=n-1;~i;i--)sa[--wt[wv[i]]]=y[i];
t=x;x=y;y=t;
p=1;
x[sa[0]]=0;
for(Ri int i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
if(p>=n)break;
}
//for(Ri int i=0;i<n;i++)cout<<sa[i]<<" ";cout<<endl;
} signed main(){
scanf("%s",s);
n=strlen(s);
for(Ri int i=0;i<n;i++)s[i+n]=s[i];
n<<=1;
//for(Ri int i=0;i<n;i++)cout<<s[i];cout<<endl;
for(Ri int i=0;i<n;i++)r[i]=s[i];
SA(r,sa,n,m);
for(Ri int i=0;i<n;i++)if(sa[i]<n/2)cout<<s[sa[i]+n/2-1];
return 0;
}

SP694 DISUBSTR - Distinct Substrings

https://www.luogu.com.cn/problem/SP694

100pts(SA模板3.0)

#include<bits/stdc++.h>
using namespace std; #define Ri register
#define ll long long
const int N=5e4+10;
int T,n,m,r[N],sa[N],wa[N],wb[N],wv[N],wt[N],ranki[N],height[N];
char s[N]; inline int cmp(int *r,int a,int b,int len){
return r[a]==r[b]&&(a+len>=n?-1:r[a+len])==(b+len>=n?-1:r[b+len]);
//更改处1:增加比较超过n的地方
}
inline void SA(int *r,int *sa,int n,int m){
int p=1,*x=wa,*y=wb,*t;
m=1010;
for(Ri int i=0;i<m;i++)wt[i]=0;
for(Ri int i=0;i<n;i++)++wt[x[i]=r[i]];
for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1];
for(Ri int i=n-1;i>=0;i--)sa[--wt[x[i]]]=i;
for(Ri int j=1;j<=n;j<<=1){
p=0;
for(Ri int i=n-j;i<n;i++)y[p++]=i;
for(Ri int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
for(Ri int i=0;i<m;i++)wt[i]=0;
for(Ri int i=0;i<n;i++)wv[i]=x[y[i]];
for(Ri int i=0;i<n;i++)++wt[wv[i]];
for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1];
for(Ri int i=n-1;i>=0;i--)sa[--wt[wv[i]]]=y[i];
p=1;
t=x;x=y;y=t;
x[sa[0]]=0;
for(Ri int i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
//cout<<"len "<<j<<endl;
//for(Ri int i=0;i<n;i++)cout<<sa[i]<<" ";cout<<endl;
m=p;
if(p>=n)break;
}
}
inline void calc(int *r,int *sa,int n){
int k=0,j;
for(Ri int i=0;i<n;i++)ranki[sa[i]]=i;
//height[0]=0;
for(Ri int i=0;i<n;i++){
if(ranki[i]==0)continue;
if(k)--k;
j=sa[ranki[i]-1];
while(i+k<n&&j+k<n&&r[i+k]==r[j+k])++k;
height[ranki[i]]=k;
}
//更改处2:更改为i为循环元素
/*for(Ri int i=0;i<n-1;height[ranki[i++]]=k)
for(k?k--:0,j=sa[ranki[i]-1];r[i+k]==r[j+k];k++);*/
//for(Ri int i=0;i<n;i++)cout<<ranki[i]<<" ";cout<<endl;
//for(Ri int i=0;i<n;i++)cout<<height[i]<<" ";cout<<endl;
} signed main(){
cin>>T;
while(T--){
scanf("%s",s);
n=strlen(s);
for(Ri int i=0;i<n;i++)r[i]=s[i];
SA(r,sa,n,m);calc(r,sa,n);
ll ans=n-sa[0];
for(Ri int i=1;i<n;i++)ans+=n-sa[i]-height[i];
cout<<ans<<endl;
}
return 0;
}

P2852 [USACO06DEC]Milk Patterns G(重复的K次最长字串:RMQ+SA)

https://www.luogu.com.cn/problem/P2852

100pts:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std; #define Ri register
const int N=2e4+10;
const int inf=0x3f3f3f3f;
int n,m,K;
int r[N],sa[N],ranki[N],height[N],wa[N],wb[N],wv[N],wt[N];
int a[N],f[N][20],logi[N]; inline int cmp(int *r,int a,int b,int len){
return r[a]==r[b]&&(a+len>=n?-1:r[a+len])==(b+len>=n?-1:r[b+len]);
}
inline void SA(int *r,int *sa,int n,int m){
m=500;
int *x=wa,*y=wb,*t,p=1;
for(Ri int i=0;i<m;i++)wt[i]=0;
for(Ri int i=0;i<n;i++)++wt[x[i]=r[i]];
for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1];
for(Ri int i=n-1;i>=0;i--)sa[--wt[x[i]]]=i;
for(Ri int j=1;j<=n;j*=2,m=p){
p=0;
for(Ri int i=n-j;i<n;i++)y[p++]=i;
for(Ri int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
for(Ri int i=0;i<m;i++)wt[i]=0;
for(Ri int i=0;i<n;i++)wv[i]=x[y[i]];
for(Ri int i=0;i<n;i++)++wt[wv[i]];
for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1];
for(Ri int i=n-1;i>=0;i--)sa[--wt[wv[i]]]=y[i];
p=1;
t=x;x=y;y=t;
x[sa[0]]=0;
for(Ri int i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
if(p>=n)break;
}
}
inline void calc(int *r,int *sa,int n){
int k=0,j=1;
for(Ri int i=0;i<n;i++)ranki[sa[i]]=i;
height[0]=0;
for(Ri int i=0;i<n;i++){
if(!ranki[i])continue;
if(k)--k;
j=sa[ranki[i]-1];
while(max(i,j)+k<n&&r[i+k]==r[j+k])++k;
height[ranki[i]]=k;
}
/*cout<<"sa "<<endl;
for(Ri int i=0;i<n;i++)cout<<sa[i]<<" ";cout<<endl;
cout<<"height "<<endl;
for(Ri int i=0;i<n;i++)cout<<height[i]<<" ";cout<<endl;*/
}
inline int find(int minn){
int tot=0,maxn=-1;
for(Ri int i=1;i<n;i++)
if(height[i]<0)maxn=max(maxn,tot),tot=0;
else{
if(height[i-1]<minn)tot=2;
else ++tot;
}
return maxn>=K;
}
inline int erfen(int l,int r){
int L=l,R=r+1,mid,ans;
while(L<=R){
mid=(L+R)>>1;
cout<<"L "<<L<<" R "<<R<<" mid "<<mid<<" ans "<<ans<<" a[ans] "<<a[ans]<<endl;
if(find(mid))L=ans=mid;
else R=mid-1;
}
return a[ans];
}
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
inline int query(int l,int r){
int k=logi[r-l];
return min(f[l][k],f[r-(1<<k)+1][k]);
} signed main(){
memset(f,inf,sizeof(f));
n=read();K=read();
logi[1]=0;logi[2]=1;
for(Ri int i=2;i<=n;i++)logi[i]=logi[i/2]+1;
//cout<<"logi "<<endl;
//for(Ri int i=1;i<=n;i++)cout<<logi[i]<<" ";cout<<endl;
for(Ri int i=0;i<n;i++)r[i]=read();
SA(r,sa,n,m);calc(r,sa,n);
for(Ri int i=1;i<n;i++)f[i][0]=a[i]=height[i];
sort(a+1,a+n+1);
int len=unique(a+1,a+n)-a-1;
//cout<<"a "<<endl;
//for(Ri int i=1;i<=len;i++)cout<<a[i]<<" ";cout<<endl;
for(Ri int i=1;i<=15;i++)
for(Ri int j=1;j+(1<<(i))-1<n;j++)
f[j][i]=min(f[j][i-1],f[j+(1<<(i-1))][i-1]);
/*cout<<"f "<<endl;
for(Ri int i=1;i<n;i++){
for(Ri int j=0;j<=4;j++)cout<<f[i][j]<<" ";
cout<<endl;
}
cout<<endl;*/
//int ans=erfen(1,len);
int ans=-1;
for(Ri int i=1;i+K-2<n;i++){
int x=query(i,i+K-2);
//cout<<i<<" "<<i+K-2<<" "<<x<<endl;
ans=max(ans,x);
}
cout<<ans;
return 0;
}

2022.02.20 SA的更多相关文章

  1. 2022.02.21 SA

    2022.02.21 SA 当我年少轻狂时,我曾拥有自由,但我并不明白它的意义.我曾拥有时间,但我没有意识到它的珍贵.我曾拥有爱,但我从未用心去体会.数十年的时间考验后,我终于理解了三者的真谛. 我已 ...

  2. ROS的安装-> rosdep init /update报错2022.02.24实测有效

    ROS的安装-> rosdep init /update报错2022.02.24实测有效   一. 解决rosdep_init问题 正常执行sudo rosdep init会报错,如下: ERR ...

  3. 2022.02.27 CF811E Vladik and Entertaining Flags

    2022.02.27 CF811E Vladik and Entertaining Flags https://www.luogu.com.cn/problem/CF811E Step 1 题意 在一 ...

  4. 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)

    2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...

  5. 2022.02.21 UB

    2022.02.21 UB 参考资料: https://zhuanlan.zhihu.com/p/141467895 https://blog.csdn.net/ghscarecrow/article ...

  6. 2022.02.04 Day1

    前言 为日后的算法面试做准备,自己也很喜欢算法这个东西,每天3~5道题. 刷题 1.leetcode 209 长度最下的子数组 题目 长度最下的子数组 大致的意思是从数组中找到长度最小的数组,并且数组 ...

  7. 2022.02.05 DAY2

    前言 今天陪老姐送对象去安庆了,上午还去了西风禅寺求了个签,第一次拿到中评签,看来今年还需要继续努力哈哈哈.一直到晚上才有时间去做点题目,今天依旧是leetcode. 题目 leetcode 1 两数 ...

  8. Redis 中常见的集群部署方案

    Redis 的高可用集群 前言 几种常用的集群方案 主从集群模式 全量同步 增量同步 哨兵机制 什么是哨兵机制 如何保证选主的准确性 如何选主 选举主节点的规则 哨兵进行主节点切换 切片集群 Redi ...

  9. python+pytest接口自动化(6)-请求参数格式的确定

    我们在做接口测试之前,先需要根据接口文档或抓包接口数据,搞清楚被测接口的详细内容,其中就包含请求参数的编码格式,从而使用对应的参数格式发送请求.例如某个接口规定的请求主体的编码方式为 applicat ...

随机推荐

  1. meterpreter中使用mimikatz获取windows密码

    进去meterpreter后getuid一下 这获得系统管理员权限 开始 加载mimikatz模块 load mimikatz 加载成功. 第一种方法: 获取登录密码的hash值 msv 上面已经是得 ...

  2. RabbitMQ入门到进阶(Spring整合RabbitMQ&SpringBoot整合RabbitMQ)

    1.MQ简介 MQ 全称为 Message Queue,是在消息的传输过程中保存消息的容器.多用于分布式系统 之间进行通信. 2.为什么要用 MQ 1.流量消峰 没使用MQ 使用了MQ 2.应用解耦 ...

  3. Docker容器内连接宿主机即CentOS的Mysql服务器

    docker的宿主机是虚拟机下的CentOS 博主最近遇到一种情况,从服务器拷贝了一份数据库在宿主机Mysql服务器上,想要用本地的数据库测试自己的代码正确性,但是项目程序都是靠docker一键部署的 ...

  4. Collection框架中实现比较要实现什么接口?

    Java集合框架中需要比较大小的集合包括TreeMap.TreeSet,其中TreeMap会根据key-value对中key的大小进行排序,而TreeSet则会对集合元素进行排序. 因此TreeMap ...

  5. 为什么需要消息系统,mysql 不能满足需求吗?

    1.解耦: 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余: 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据 丢失风险.许多消息队列所采用的& ...

  6. 在Spring AOP 中,关注点和横切关注的区别是什么?

    关注点是应用中一个模块的行为,一个关注点可能会被定义成一个我们想实现的一个功能. 横切关注点是一个关注点,此关注点是整个应用都会使用的功能,并影响整个应用,比如日志,安全和数据传输,几乎应用的每个模块 ...

  7. MariaDB 存储引擎一览(官方文档翻译)

    inline-translate.translate { } inline-translate.translate::before, inline-translate.translate::after ...

  8. 什么是 bean 装配?

    装配,或 bean 装配是指在 Spring 容器中把 bean 组装到一起,前提是容器需要 知道 bean 的依赖关系,如何通过依赖注入来把它们装配到一起.

  9. 遇到的问题之“Dubbo 直连 Invoke remote method timeout 问题!”

    Dubbo 直连 Invoke remote method timeout 问题!   在测试环境消费者直连服务端进行测试时, 其中一个RPC接口抛出一个错误, 如下: Caused by: com. ...

  10. can总线第二讲

    一 CAN总线拓扑结构CAN是一种分布式的控制总线,总线上的每一个节点一般来说都比较简单,使用MCU控制器处理CAN总线数据,完成特定的功能:通过CAN总线将各节点连接只需较少的线缆(两根线:CAN_ ...