洛谷P1638 逛画展 (尺取法)
尺取法的经典题目:
博览馆正在展出由世上最佳的 mm 位画家所画的图画。
游客在购买门票时必须说明两个数字,aa 和 bb,代表他要看展览中的第 aa 幅至第 bb 幅画(包含 a,ba,b)之间的所有图画,而门票的价钱就是一张图画一元。
Sept 希望入场后可以看到所有名师的图画。当然,他想最小化购买门票的价格。
请求出他购买门票时应选择的 a,ba,b,数据保证一定有解。
若存在多组解,输出 aa 最小的那组。
首次了解到有尺取法这个东西,实际上就是双指针维护。用从cnt[i]维护区间每种画的个数,双指针扫描即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define int long long 4 const int N=1e6+10; 5 int n,m,x,sum,y=1e9,a[N],cnt[N];//用从cnt[i]维护区间每种画的个数 6 7 signed main(){ 8 cin>>n>>m; 9 for(int i=1;i<=n;i++) cin>>a[i]; 10 int l=1,r=1;//双指针扫描 11 while(l<=r&&r<=n){ 12 while(sum<m&&r<=n){//移动右指针 13 if(!cnt[a[r]]) sum++; 14 cnt[a[r]]++; 15 r++; 16 } 17 if(sum<m) break; 18 if(r-l<y-x+1) x=l,y=r-1;//更新答案区间 19 //if((r-1)-l+1<y-x+1) x=l,y=r-1; 20 if(cnt[a[l]]==1) sum--; 21 cnt[a[l]]--; 22 l++;//移动左指针 23 } 24 cout<<x<<" "<<y; 25 return 0; 26 }