【洛谷】P1638 逛画展(双指针)

方法:区间伸缩

时间复杂度:O(n)

用两个变量l和r来枚举区间

如果l到r的区间不满足要求,r++

如果l到r的区间满足要求,记录答案,l++

ACcode:(详细注释,安全食用~)

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10,M=2e3+10;
int a[N],b[M],n,m,L,R,k;
void solve(){
  cin>>n>>m;
  for(int i=1;i<=n;i++) cin>>a[i];
  int l=1,r=1,ans=1<<30;
  b[a[1]]=1,k=1;//当前区间中画家出现的次数,当前区间有多少个画家
  //因为r,l=初始化为1,即认为a[1]画家已经在当前区间内,所以:b[a[i]]=1,k=1
  while(l<=r&&r<=n){
  	if(k==m){//当前有区间有m个画家了,满足要求,
	  //那r(右指针就先不用动,开始移动左指针向右)
	  //看是不是l向右移动当前区间是不是还是m个画家 
	  
  		if(ans>r-l+1){//更新最小区间 
  			ans=r-l+1;
  			L=l,R=r;//标记最小区间,方便输出 
		  } 
		  
		  b[a[l]]--; 
		  if(b[a[l]]==0) k--;//左指针向右移动导致该区间本来只有该画家的唯一幅画也没了  
		  //那该画家这不在当前k画家中了,所以k-- 
		  //k--一旦减一下一就会进入else(又轮到右指针r寻找不够的那几个画家) 
		  l++;//左指针向右移动 
	  }
	  else{
	  	r++;
	  	b[a[r]]++;
	  	if(b[a[r]]==1)k++;//等于1代表当前画家是第一次出现,
		  //所以K要+1,(明确k的含义) 
	  }
  } 
  cout<<L<<" "<<R<<"\n"; 
}
int main() {
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	solve();
	return 0;
}

over~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值