2022.02.20 SA
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 关于判断越界
有两种方法:
手动判断越界
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]);
}
字符串末尾加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的更多相关文章
- 2022.02.21 SA
2022.02.21 SA 当我年少轻狂时,我曾拥有自由,但我并不明白它的意义.我曾拥有时间,但我没有意识到它的珍贵.我曾拥有爱,但我从未用心去体会.数十年的时间考验后,我终于理解了三者的真谛. 我已 ...
- ROS的安装-> rosdep init /update报错2022.02.24实测有效
ROS的安装-> rosdep init /update报错2022.02.24实测有效 一. 解决rosdep_init问题 正常执行sudo rosdep init会报错,如下: ERR ...
- 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 题意 在一 ...
- 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)
2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...
- 2022.02.21 UB
2022.02.21 UB 参考资料: https://zhuanlan.zhihu.com/p/141467895 https://blog.csdn.net/ghscarecrow/article ...
- 2022.02.04 Day1
前言 为日后的算法面试做准备,自己也很喜欢算法这个东西,每天3~5道题. 刷题 1.leetcode 209 长度最下的子数组 题目 长度最下的子数组 大致的意思是从数组中找到长度最小的数组,并且数组 ...
- 2022.02.05 DAY2
前言 今天陪老姐送对象去安庆了,上午还去了西风禅寺求了个签,第一次拿到中评签,看来今年还需要继续努力哈哈哈.一直到晚上才有时间去做点题目,今天依旧是leetcode. 题目 leetcode 1 两数 ...
- Redis 中常见的集群部署方案
Redis 的高可用集群 前言 几种常用的集群方案 主从集群模式 全量同步 增量同步 哨兵机制 什么是哨兵机制 如何保证选主的准确性 如何选主 选举主节点的规则 哨兵进行主节点切换 切片集群 Redi ...
- python+pytest接口自动化(6)-请求参数格式的确定
我们在做接口测试之前,先需要根据接口文档或抓包接口数据,搞清楚被测接口的详细内容,其中就包含请求参数的编码格式,从而使用对应的参数格式发送请求.例如某个接口规定的请求主体的编码方式为 applicat ...
随机推荐
- meterpreter中使用mimikatz获取windows密码
进去meterpreter后getuid一下 这获得系统管理员权限 开始 加载mimikatz模块 load mimikatz 加载成功. 第一种方法: 获取登录密码的hash值 msv 上面已经是得 ...
- RabbitMQ入门到进阶(Spring整合RabbitMQ&SpringBoot整合RabbitMQ)
1.MQ简介 MQ 全称为 Message Queue,是在消息的传输过程中保存消息的容器.多用于分布式系统 之间进行通信. 2.为什么要用 MQ 1.流量消峰 没使用MQ 使用了MQ 2.应用解耦 ...
- Docker容器内连接宿主机即CentOS的Mysql服务器
docker的宿主机是虚拟机下的CentOS 博主最近遇到一种情况,从服务器拷贝了一份数据库在宿主机Mysql服务器上,想要用本地的数据库测试自己的代码正确性,但是项目程序都是靠docker一键部署的 ...
- Collection框架中实现比较要实现什么接口?
Java集合框架中需要比较大小的集合包括TreeMap.TreeSet,其中TreeMap会根据key-value对中key的大小进行排序,而TreeSet则会对集合元素进行排序. 因此TreeMap ...
- 为什么需要消息系统,mysql 不能满足需求吗?
1.解耦: 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余: 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据 丢失风险.许多消息队列所采用的& ...
- 在Spring AOP 中,关注点和横切关注的区别是什么?
关注点是应用中一个模块的行为,一个关注点可能会被定义成一个我们想实现的一个功能. 横切关注点是一个关注点,此关注点是整个应用都会使用的功能,并影响整个应用,比如日志,安全和数据传输,几乎应用的每个模块 ...
- MariaDB 存储引擎一览(官方文档翻译)
inline-translate.translate { } inline-translate.translate::before, inline-translate.translate::after ...
- 什么是 bean 装配?
装配,或 bean 装配是指在 Spring 容器中把 bean 组装到一起,前提是容器需要 知道 bean 的依赖关系,如何通过依赖注入来把它们装配到一起.
- 遇到的问题之“Dubbo 直连 Invoke remote method timeout 问题!”
Dubbo 直连 Invoke remote method timeout 问题! 在测试环境消费者直连服务端进行测试时, 其中一个RPC接口抛出一个错误, 如下: Caused by: com. ...
- can总线第二讲
一 CAN总线拓扑结构CAN是一种分布式的控制总线,总线上的每一个节点一般来说都比较简单,使用MCU控制器处理CAN总线数据,完成特定的功能:通过CAN总线将各节点连接只需较少的线缆(两根线:CAN_ ...