题目大意:
有一个数列,每次去掉前某一个page里面的所有指定元素,删除后,后面的元素可以往前蹭。每个page固定包含一定数量的元素。 问:需要执行多少次删除操作。
解题思路:
很自然的最naive 的做法是:删除指定区间的时候,后面的所有元素都改变自己的位置。但是这样会导致o(m^2)。其实这里有一个special page,这个special page明确了我们每次只可以取部分元素,这使得我们没必要盲目的删除一个元素就把后面所有的元素的位置都减一。我们每次只需遍历special page里面的元素。遍历到这个元素时,我们减去累计已经删除的元素个数的位置,从而达到删除后位移的目的。
废话:
这题也不难,但是就是没想到,哎!以后O(n)的算法,要提醒自己从线性遍历的角度考虑。
#include <bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
int32_t main(){
ll n,m,k;
cin>>n>>m>>k;
queue<int> q;
for(int i=0;i<m;i++){
int t;cin>>t;
t-=1;
q.push(t);
}
int ans=0;
int sum=0;
while(!q.empty()){
int tmpsum=0;
while(!q.empty()){
int no=q.front();
no-=sum;
int l,r;
if(!tmpsum){
l=no/k;
l*=k;
r=no/k+1;
r*=k;
tmpsum+=1;
ans++;
q.pop();
continue;
}
if(no< l || no>=r)break;
tmpsum++;
q.pop();
}
sum+=tmpsum;
}
cout<<ans<<endl;
}