【与循环有关的问题】

【与循环有关的问题】

一般是把数组再复制一遍
然后观察数组与下标的关系

战前准备

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;
}
posted @ 2025-07-12 21:00  White_ink  阅读(4)  评论(0)    收藏  举报