【与循环有关的问题】
【与循环有关的问题】
一般是把数组再复制一遍
然后观察数组与下标的关系
战前准备
https://ac.nowcoder.com/acm/contest/112575/C
题目大意
对一个数组可以进行k循环移位(把后面的拿到前面去)
对于每一个数(0<x<m),设在数组中第一次出现的位置为p[x]
要满足所有x p[x]<p[x+1]
求满足条件的k循环移位数组有多少个
思路
循环移位->数组加长一倍即可
设刚开始设所有数*均不满足条件*(逆序) 从尾到头遍历
设pos[v]为*最后一次*出现v的位置->以最后一次来代替首次
m个数有cnt=m-1组关系->当i<=n时可以开始计ans:当cnt==0时该点可行
先判断再更新
(1)当pos[a[i]]>pos[a[i]-1]时:
代表当前点更新后a[i]会在a[i]-1前面->不满足条件 cnt++
a[i] pos[a[i]-1] pos[a[i]]
○ ○ ○
(2)当pos[a[i]+1]<pos[a[i]]时:
代表当前点更新后a[i]会在a[i]+1前面->满足条件 cnt--
a[i] pos[a[i]+1] pos[a[i]]
○ ○ ○
->有两种情况不用考虑的:没有意义 说明不了什么 更新一下位置即可
pos[a[i]]<pos[a[i]-1]
a[i] pos[a[i]] pos[a[i]-1]
○ ○ ○
pos[a[i]]<pos[a[i]+1]
a[i] pos[a[i]] pos[a[i]+1]
○ ○ ○
代码
int n,m;
void solve(){
cin>>n>>m;
vector<int> a(n+1,0);
for(int i=1;i<=n;i++) cin>>a[i];
vector<int> s(2*n+5,0);
for(int i=1;i<=n;i++) s[i]=a[i];
for(int i=n+1;i<=2*n;i++) s[i]=a[i-n];
vector<int> pos(m+5,0);
//开局逆序
for(int i=0;i<m;i++){
pos[i]=2*n+m-i;
}
int cnt=m-1;
int ans=0;
for(int i=2*n-1;i>=1;i--){
int v=s[i];
if(v>0 && pos[v]>pos[v-1]) cnt++;
if(v<m-1 && pos[v]>pos[v+1]) cnt--;
if(i<=n && cnt==0) ans++;
pos[v]=i;
}
cout<<ans<<endl;
}