BZOJ-1293 [SCOI2009]生日禮物(尺取法)
阿新 • • 發佈:2020-12-11
題目描述
彩珠有 \(1\leq n\leq 10^6\) 個,分為 \(1\leq k\leq 60\) 種。可以將綵帶考慮為 \(x\) 軸,每一個彩珠有一個對應的座標(即位置)。某些座標上可以沒有彩珠,但多個彩珠也可以出現在同一個位置上。剪一段綵帶,能包含所有種類的彩珠,同時使綵帶儘可能短,求最短的長度。
分析
記錄每個彩珠的顏色和位置,按位置從小到大排序,尺取法,右指標右移的時候記錄顏色 \(i\) 出現了 \(tot[i]\) 次,記錄當前不同顏色數 \(sum\),\(sum=k\) 時左指標右移,刪去對應顏色出現的次數和不同顏色數。
程式碼
#include<bits/stdc++.h> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();} while (isdigit(ch)){x=x*10+ch-48;ch=getchar();} return x*f; } const int N=1e6+10; const int INF=0x3f3f3f3f; struct node { int pos; int ID; }a[N],temp[N]; int tot[N]; bool cmp(node A,node B) { return A.pos<B.pos; } int main() { int n,k,cnt=0; cin>>n>>k; for(int i=1;i<=k;i++) { int x=read(); for(int j=1;j<=x;j++) { cnt++; a[cnt].pos=read(); a[cnt].ID=i; } } sort(a+1,a+1+cnt,cmp); int ans=INF; int l=1,r=0,sum=0; for(int i=1;i<=n;i++) { r++; temp[r].pos=a[i].pos; temp[r].ID=a[i].ID; tot[a[i].ID]++; if(tot[a[i].ID]==1) sum++; while(sum==k) { ans=min(ans,temp[r].pos-temp[l].pos); tot[temp[l].ID]--; if(tot[temp[l].ID]==0) sum--; l++; } } cout<<ans<<endl; return 0; }