我发现BZOJ的水题都比较高档昂。这道题的基本思想是,每次用优先队列把位置最靠前的颜色弹出来,并把与它颜色相同的下一个点的位置进队列,每次更新最优长度。
1.初始化:每个点的下一个相同颜色点的位置。
2.将每个颜色的第一个点入队列,算第一个状态。
3.每次将队列最前端的颜色弹出,将他的下一个点放入队列,更新最优长度。
注:cmp函数、重载运算符有的时候需要加“const”“&”等奇怪的符号,一直都不太懂什么意思,怎么用,求神犇指教。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<utility>
#include<queue>
#define MAXN 1000010
#define INF (1<<30)
using namespace std;
int t[61],s[61];
struct node{
int first;
int second;
int next;
node(){};
void init(int x,int y,int z){
first=x;
second=y;
next=z;
}
friend bool operator < (node a,node b){
return a.second>b.second;
}
}x[MAXN];
priority_queue<node> q;
int main(){
s[0]=0;
int n,k,l,r=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++){
scanf("%d",&s[i]);
s[i]=s[i]+s[i-1];
for(int j=s[i-1]+1;j<=s[i];j++) {
int a;
scanf("%d",&a);
x[j].init(i,a,j+1);
}
}
for(int i=0;i<k;i++) {
r=max(r,x[s[i]+1].second);
q.push(x[s[i]+1]);
}
int ans=r-q.top().second;
while(1){
node tmp=q.top();
q.pop();
if(tmp.next-1<s[tmp.first]) {
r=max(x[tmp.next].second,r);
q.push(x[tmp.next]);
}
else break;
tmp=q.top();
ans=min(r-tmp.second,ans);
}
printf("%d",ans);
return 0;
}