【BZOJ- 1293】生日禮物 (尺取法)
阿新 • • 發佈:2018-11-28
小西有一條很長的綵帶,綵帶上掛著各式各樣的彩珠。已知彩珠有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。
思路:
很明顯的尺取,開始終點移動走過一個點就把這個點上的所有珠寶都加入佇列,當珠寶種類大於k時,起點移動,讓珠寶出佇列。不過要注意當一個點上的珠寶種類的數量正好為k是,其長度為1。從這道題也學到了pair和優先佇列的結合使用,記一下。
ac程式碼:
#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<stack> #include<string.h> #include<set> #define ll long long #define PI acos(-1.0) #define eps 1e-8 using namespace std; typedef pair<int,int> pii; pair<int,int> p1; map<int,int> mp; struct cmp{ bool operator() (const pii p1,const pii p2){ return p1.first > p2.first; /// first 小的先彈出 } }; int main() { /* 這裡不用優先佇列也可以,將資訊存在一個結構體陣列中,按照位置排一下序,然後掃一遍,掃到一個往後看看有沒有位置和這個相同的,有就都加進來。 或者用二維的vector,掃到一個點,把這一點對應的這一列都加入,求這一列的長度時,先定義一個變數接收size,否則在迴圈中寫size()的話時間複雜度是O(n) */ //priority_queue<pair<int,int>,vector<pii>,greater<pii> > que,q2; //也可以用上面的寫法 priority_queue<pair<int,int>,vector<pii>,cmp> que,q2; int len=0x3f3f3f3f; int n,k; scanf("%d%d",&n,&k); int num=0; for(int i=1;i<=k;i++) { p1.second=i; int t; scanf("%d",&t); for(int j=0;j<t;j++) { int wi; scanf("%d",&wi); p1.first=wi; que.push(p1); } } int st=que.top().first; int ed=que.top().first; while(!(que.empty()&&q2.empty())) { while(num<k&&!que.empty()) { p1=que.top(); que.pop(); ed=p1.first; if(mp[p1.second]==0) num++; mp[p1.second]++; q2.push(p1); while(!que.empty()&&que.top().first==p1.first) { pair<int,int> p2; p2=que.top(); que.pop(); if(mp[p2.second]==0) num++; mp[p2.second]++; q2.push(p2); } } while(num==k&&!q2.empty()) { int tt=ed-st; if(st==ed) tt=1; len=min(len,tt); p1=q2.top(); q2.pop(); mp[p1.second]--; if(mp[p1.second]==0) num--; while(!q2.empty()&&q2.top().first==p1.first) { pair<int,int> p2; p2=q2.top(); q2.pop(); mp[p2.second]--; if(mp[p2.second]==0) num--; } st=q2.top().first; } if(num<k&&que.empty()) break; } printf("%d\n",len); return 0; }