1. 程式人生 > >刷題總結——生日禮物(bzoj1293單調隊列)

刷題總結——生日禮物(bzoj1293單調隊列)

希望 100% 一段 des 同時 code urn blog 接下來

題目:

Description

小西有一條很長的彩帶,彩帶上掛著各式各樣的彩珠。已知彩珠有N個,分為K種。簡單的說,可以將彩帶考慮為x軸,每一個彩珠有一個對應的坐標(即位置)。某些坐標上可以沒有彩珠,但多個彩珠也可以出現在同一個位置上。 小布生日快到了,於是小西打算剪一段彩帶送給小布。為了讓禮物彩帶足夠漂亮,小西希望這一段彩帶中能包含所有種類的彩珠。同時,為了方便,小西希望這段彩帶盡可能短,你能幫助小西計算這個最短的長度麽?彩帶的長度即為彩帶開始位置到結束位置的位置差。

Input

第一行包含兩個整數N, K,分別表示彩珠的總數以及種類數。接下來K行,每行第一個數為Ti,表示第i種彩珠的數目。接下來按升序給出Ti個非負整數,為這Ti個彩珠分別出現的位置。

Output

應包含一行,為最短彩帶長度。

Sample Input

6 3
1 5
2 1 7
3 1 3 8

Sample Output

3

HINT

有多種方案可選,其中比較短的是1~5和5~8。後者長度為3最短。
【數據規模】
對於50%的數據, N≤10000;
對於80%的數據, N≤800000;
對於100%的數據,1≤N≤1000000,1≤K≤60,0≤彩珠位置<2^31。

題解:

先開始讀錯題了卡了半天23333

一道單調隊列的簡單題···註意邊界條件就行···先將珠子按照位置排序,維護一個單調隊列就好了,過程類似於莫隊時的維護答案····註意下邊界條件就好了

代碼:

#include<iostream>
#include
<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> using namespace std; const int N=1e6+5; const int M=105; struct node { int p,c; }b[N]; int n,m,k,queue[N],head,tail,tot,cnt[M],now,ans=0x7f7f7f7f
; inline int R() { char c;int f=0; for(c=getchar();c<0||c>9;c=getchar()); for(;c<=9&&c>=0;c=getchar()) f=(f<<3)+(f<<1)+c-0; return f; } inline bool cmp(node a,node b) { return a.p<b.p; } int main() { freopen("a.in","r",stdin); n=R(),m=R(); for(int i=1;i<=m;i++) { k=R(); for(int j=1;j<=k;j++) b[++tot].p=R(),b[tot].c=i; } sort(b+1,b+tot+1,cmp); head=tail=1;cnt[b[1].c]++,now=1; for(;head<=tot;head++) { while(now<m&&tail<=tot) { tail++; if(!cnt[b[tail].c]) now++; cnt[b[tail].c]++; } if(tail==tot+1) break; if(now==m) ans=min(ans,b[tail].p-b[head].p); cnt[b[head].c]--; if(!cnt[b[head].c]) now--; } cout<<ans<<endl; return 0; }

刷題總結——生日禮物(bzoj1293單調隊列)