洛谷P2564 [SCOI2009]生日禮物
阿新 • • 發佈:2020-12-12
題意
分析
一道單調佇列的應用
(其實有點不像是單調佇列)
大概就是先按照座標軸排序,依次處理
維護一個佇列儲存當前在佇列中的每個球(記錄其下標)
然後對於每一個區間一定有右端點和一個左端點
列舉右端點,左端點單調佇列維護,可以求得最右的左端點的下標
然後維護過程就是每次看當前這個顏色的\(cnt\)陣列是否\(>1\),如果是,那麼就可以不要這個點,這個點出隊,如果不是,那麼保留
程式碼
#include<bits/stdc++.h> using namespace std; template <typename T> inline void read(T &x){ x=0;char ch=getchar();bool f=false; while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x=f?-x:x; return ; } template <typename T> inline void write(T x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10^48); return ; } const int N=1000005; int n,k,op,idx,cnt[N],now,ans=0x3f3f3f3f,hh,tt=-1,que[N]; struct node{int x,id;}a[N]; inline bool cmp(node x,node y){return x.x<y.x;} int main(){ read(n),read(k); for(int i=1;i<=k;i++){ read(op); for(int j=1;j<=op;j++){ read(a[++idx].x); a[idx].id=i; } } sort(a+1,a+idx+1,cmp); for(int i=1;i<=n;i++){ if(cnt[a[i].id]==0) now++; cnt[a[i].id]++; que[++tt]=i; while(hh<=tt&&cnt[a[que[hh]].id]>1) cnt[a[que[hh++]].id]--; if(now==k) ans=min(ans,a[i].x-a[que[hh]].x); } write(ans); return 0; }