个人心得:做完这题发现自己有多水,先是思路崩盘,后面借鉴思路之后再试,编程崩盘。好吧,全程崩盘,我要很无奈。
总的来说,还是自己思维的不严谨性和不会更好的模拟和运用学过的知识,还是有待进步!
好吧先看这道令我奔溃的题吧,可能是我太水了!!!
小西有一条很长的彩带,彩带上挂着各式各样的彩珠。已知彩珠有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。
做题思路:本来是想从上到下一直延伸的,发现实施不了,后想着每个来一次深搜,绝对超时,后面看了网上的思路。很令人佩服。
【分析】:
这道题用贪心的思想。贪心的方法为:对于每种颜色的彩珠,从编号小的地方往后推进,用数组where[x]记录x颜色的珠子已经推进到了哪个地方。首先,在所有颜色当前推进位置中,选出位置编号的最大值max1和最小值min1,很容易想到当前符合题意的长度就是max1-min1<如图一>,这一步是计算。
然后尝试将某个满足下面条件的颜色的where向后推一位:这一颜色的当前推进位置是所有颜色中最小的,且它的后面那一位最小,这一步是转移<如图二>。
现在来计算循环次数:有N个珠子,K种颜色,转移需转移N-K次,计算需计算N-K+1次<多的“1”是在初始位置时需要进行一次计算>,因此循环次数为N-K+1。这道题贪心之处就在于每次转移最小值,这样保证情况最优且考虑全面。
【时间复杂度分析】:
循环次数*(转移+计算):O((N-K+1)*2*K)=O(N*K)
个人心得:挺不错的思想,可是实施起来比较麻烦,每次选最小的,后面看到其他的大神用了优先队列发现挺完美,不过终止条件和结构体的建立要思考,结构体必须包括他所属的颜色和在的位置,答案的代码是直接建立最大数据的结构体数组,一个颜色标志,一个存储位置,还有个就是存储下一个同等颜色的位置,
我发现BZOJ的水题都比较高档昂。这道题的基本思想是,每次用优先队列把位置最靠前的颜色弹出来,并把与它颜色相同的下一个点的位置进队列,每次更新最优长度。
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 }