bzoj1293: [SCOI2009]生日礼物

Posted invoid

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1293: [SCOI2009]生日礼物相关的知识,希望对你有一定的参考价值。

单调队列

用一个堆维护目前每个颜色在里面的点,每回取出队首点,并更新答案。一旦哪个颜色的点都被用完,跳出循环。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 1000000 + 10;
const int maxk = 60+10;

struct data {
    int a,c;
    
    data(int a,int c):a(a),c(c) {}
    
    bool operator < (const data& rhs) const {
        return a>rhs.a;
    }
};
priority_queue<data>q;
int n,k;
int w[maxk],a[maxn];
int v[maxn],next[maxn],eid,g[maxk];
int ans,tmp;

void addedge(int a,int b) {
    v[eid]=b; next[eid]=g[a]; g[a]=eid++;
}

int main() {
    memset(g,-1,sizeof(g));
    scanf("%d%d",&n,&k);
    for(int i=1;i<=k;i++) {
        scanf("%d",&w[i]);
        for(int j=1;j<=w[i];j++) scanf("%d",&a[j]);
        for(int j=w[i];j;j--) addedge(i,a[j]);
    }
    for(int i=1;i<=k;i++) {
        q.push(data(v[g[i]],i));
        tmp=max(v[g[i]],tmp);
    }
    ans=tmp-q.top().a;
    while(true) {
        data u=q.top(); q.pop();
        //printf("test %d %d \n",u.a,u.c);
        //printf("ok %d %d\n",tmp,ans);
        g[u.c]=next[g[u.c]];
        if(g[u.c]==-1) break;
        q.push(data(v[g[u.c]],u.c));
        tmp=max(tmp,v[g[u.c]]);
        ans=min(ans,tmp-q.top().a);
    }
    printf("%d\n",ans);
    return 0;
}

以上是关于bzoj1293: [SCOI2009]生日礼物的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ-1293: [SCOI2009]生日礼物 (单调队列)

bzoj1293[SCOI2009]生日礼物 尺取法

[bzoj1293][SCOI2009]生日礼物

bzoj 1293: [SCOI2009]生日礼物

bzoj1293: [SCOI2009]生日礼物

bzoj1293: [SCOI2009]生日礼物