个人心得:做完这题发现自己有多水,先是思路崩盘,后面借鉴思路之后再试,编程崩盘。好吧,全程崩盘,我要很无奈。
总的来说,还是自己思维的不严谨性和不会更好的模拟和运用学过的知识,还是有待进步!
好吧先看这道令我奔溃的题吧,可能是我太水了!!!
小西有一条很长的彩带,彩带上挂着各式各样的彩珠。已知彩珠有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。
做题思路:本来是想从上到下一直延伸的,发现实施不了,后想着每个来一次深搜,绝对超时,后面看了网上的思路。很令人佩服。
1.初始化:每个点的下一个相同颜色点的位置。
2.将每个颜色的第一个点入队列,算第一个状态。
3.每次将队列最前端的颜色弹出,将他的下一个点放入队列,更新最优长度。
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<algorithm> 5 #include<utility> 6 #include<queue> 7 #define MAXN 1000010 8 #define INF (1<<30) 9 using namespace std; 10 int t[61],s[61]; 11 struct node{ 12 int first; 13 int second; 14 int next; 15 node(){}; 16 void init(int x,int y,int z){ 17 first=x; 18 second=y; 19 next=z; 20 } 21 friend bool operator < (node a,node b){ 22 return a.second>b.second; 23 } 24 }x[MAXN]; 25 priority_queue<node> q; 26 int main(){ 27 s[0]=0; 28 int n,k,l,r=0; 29 scanf("%d%d",&n,&k); 30 for(int i=1;i<=k;i++){ 31 scanf("%d",&s[i]); 32 s[i]=s[i]+s[i-1]; 33 for(int j=s[i-1]+1;j<=s[i];j++) { 34 int a; 35 scanf("%d",&a); 36 x[j].init(i,a,j+1); 37 } 38 } 39 for(int i=0;i<k;i++) { 40 r=max(r,x[s[i]+1].second); 41 q.push(x[s[i]+1]); 42 } 43 int ans=r-q.top().second; 44 while(1){ 45 node tmp=q.top(); 46 q.pop(); 47 if(tmp.next-1<s[tmp.first]) { 48 r=max(x[tmp.next].second,r); 49 q.push(x[tmp.next]); 50 } 51 else break; 52 tmp=q.top(); 53 ans=min(r-tmp.second,ans); 54 } 55 printf("%d",ans); 56 return 0; 57 }