【BZOJ2587】【CEOI2011】Teams
动态规划+堆即可。
将从大到小排序,容易发现每一个团队都是一个区间。
考虑暴力DP:设为前个人最多分成的团队个数,为前个人分成个团队,最大的团队的最少成员数。
易得
考虑用一个链表维护处新增的决策点,计算好后把其添加到处的链表中。
注意到相对为常数,而单调递增,那么一个随的增加,应该先取再取。
考虑再使用一个链表维护处有哪些满足,计算好后把其添加到处的链表中。
对于,用一个堆维护的最大值及取最大时的最小值。
对于,直接记录的最大值及取最大时的最大值即可。
时间复杂度。
本题存在时间复杂度的做法,参见lych_cys的题解 。
#include <bits/stdc++.h>#include <ext/pb_ds/priority_queue.hpp>using namespace std;typedef long long ll;const int MAXSIZE=30000020;const int INF=0x3f3f3f3f;int bufpos;char buf[MAXSIZE];#define NEG 0void init(){#ifdef LOCALfreopen("2587.txt","r",stdin);#endifbuf[fread(buf,1,MAXSIZE,stdin)]='\0';bufpos=0;}#if NEGint readint(){bool isneg;int val=0;for(;!isdigit(buf[bufpos]) && buf[bufpos]!='-';bufpos++);bufpos+=(isneg=buf[bufpos]=='-');for(;isdigit(buf[bufpos]);bufpos++)val=val*10+buf[bufpos]-'0';return isneg?-val:val;}#elseint readint(){int val=0;for(;!isdigit(buf[bufpos]);bufpos++);for(;isdigit(buf[bufpos]);bufpos++)val=val*10+buf[bufpos]-'0';return val;}#endifchar readchar(){for(;isspace(buf[bufpos]);bufpos++);return buf[bufpos++];}int readstr(char* s){int cur=0;for(;isspace(buf[bufpos]);bufpos++);for(;!isspace(buf[bufpos]);bufpos++)s[cur++]=buf[bufpos];s[cur]='\0';return cur;}int cnt[1000002],tmp[1000002],a[1000002],b[1000002],f[1000002],g[1000002],lst[1000002];int nxt[1000002],first[1000002],nxt2[1000002],first2[1000002];void add(int p,int v){nxt[v]=first[p];first[p]=v;}void add2(int p,int v){nxt2[v]=first2[p];first2[p]=v;}struct cmp{bool operator ()(const int &x,const int &y){return f[x]<f[y] || (f[x]==f[y] && g[x]>g[y]);}};typedef __gnu_pbds::priority_queue<int,cmp> heap;heap q;heap::point_iterator it[1000001];int main(){init();int n=readint();for(int i=1;i<=n;i++)tmp[i]=readint(),cnt[tmp[i]]++;for(int i=n;i;i--)cnt[i]+=cnt[i+1];for(int i=1;i<=n;i++)b[cnt[tmp[i]]]=i,a[cnt[tmp[i]]--]=tmp[i];int now=0;//for(int i=1;i<=n;i++)//printf("%d ",a[i]);for(int i=1;i<=n;i++){ //g[j]+j<=i//puts("WTF");for(int to=first2[i];to;to=nxt2[to]){if (g[to]+to<i){if (f[to]>=f[now])now=to;}else {//printf("adding %d\n",to);it[to]=q.push(to);}}//puts("233");for(int j=first[i];j;j=nxt[j]){if (j+a[j+1]>i)continue;//printf("%d\n",j);q.erase(it[j]);if (f[j]>f[now] || (f[j]==f[now] && j>now))now=j;}//puts("tat");if (q.empty()){if (!now && i<a[1]){g[i]=INF;continue;}f[i]=f[now]+1;g[i]=i-now;lst[i]=now;}else{int x=q.top();if (f[x]==f[now]){f[i]=f[x]+1;if (i-now<g[x])g[i]=i-now,lst[i]=now;else g[i]=g[x],lst[i]=x;}else if (f[x]<f[now])f[i]=f[now]+1,g[i]=i-now,lst[i]=now;else f[i]=f[x]+1,g[i]=g[x],lst[i]=x;}//puts("qwq");//printf("f[%d]=%d\n",i,f[i]);if (g[i]+i<=n)add(g[i]+i,i);if (i<n && i+a[i+1]<=n)add2(i+a[i+1],i);}printf("%d\n",f[n]);for(int i=n;i;){int w=lst[i];printf("%d ",i-w);while(i>w){printf("%d ",b[i]);i--;}putchar('\n');}}
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
本文链接:https://www.q234rty.top/2017/09/23/bzoj2587/
