洛谷P1638 逛画展
题目大意:
画展中有n排好序幅画,分别由m位画家所画,看一幅画一元,问从第几幅看到第几幅既能看遍所有画家的至少一幅作品,还能省钱。(N<=1000000 , M<=2000)
思路:
按钱数二分。check时,用一个数组记录可以看到的每个画家的作品数,在记录一个所看到画家数,移动长度为钱数的区间,查看加进来的和出去的并更新作品数和画家数,当画家数为m就合理。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 6 using namespace std; 7 8 int n,m,a[1000006],ansr,ansl,have[2002]; 9 10 bool check(int paint) 11 { 12 memset(have,0,sizeof(have)); 13 int youxiao=0; 14 int i=1,j=paint; 15 for(int k=1;k<=paint;k++) 16 { 17 have[a[k]]++; 18 if(have[a[k]]==1)youxiao++; 19 } 20 while(j<=n) 21 { 22 if(youxiao==m) 23 { 24 ansl=i; 25 ansr=j; 26 return true; 27 } 28 have[a[i]]--; 29 if(!have[a[i]])youxiao--; 30 i++; 31 j++; 32 have[a[j]]++; 33 if(j<=n&&have[a[j]]==1)youxiao++; 34 } 35 return false; 36 } 37 38 int main() 39 { 40 scanf("%d%d",&n,&m); 41 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 42 int l,r; 43 l=1;r=n; 44 while(l<r) 45 { 46 int mid=(l+r)/2; 47 if(check(mid)) 48 { 49 r=mid; 50 } 51 else 52 { 53 l=mid+1; 54 } 55 } 56 if(check(r)); 57 printf("%d %d\n",ansl,ansr); 58 return 0; 59 }