[BZOJ1293]SCOI2009生日礼物|贪心
2015-05-04 21:05
393 查看
这题好像有很多的乱搞方法。。我想的方法是贪心,考虑以i为右端点的最小覆盖了全部颜色的区间的左端点l,发现i增加的时候l显然是不降的,那就好办了,从1-n扫一遍,不断维护l,不断更新答案就行了。。
还有一种做法是弄出每种颜色出现的第一个位置和下一个位置,一开始把所有第一个位置找出来,放进一个堆,然后更新答案,每次把最左的那个颜色取出,将它的下一个位置加入堆,不断更新答案。。
还有一种做法是弄出每种颜色出现的第一个位置和下一个位置,一开始把所有第一个位置找出来,放进一个堆,然后更新答案,每次把最左的那个颜色取出,将它的下一个位置加入堆,不断更新答案。。
#include<cstdio> #include<iostream> #include<algorithm> #define N 1000005 #define inf 0x3fffffff using namespace std; struct edge{ int col,next; }ed ; struct num{ int x,xu; }q ; int n,k,i,j,t,x,l,kind,ans=inf,ne=0,cnt=0,tot=0,newq ,a ,u[65]; bool f; bool cmp(num a,num b){return a.x<b.x;} void add(int s,int col) { ed[++ne].col=col;ed[ne].next=a[s];a[s]=ne; } int main() { scanf("%d%d",&n,&k); for (i=1;i<=k;i++) { scanf("%d",&t); u[i]=0; for (j=1;j<=t;j++) scanf("%d",&x),q[++cnt].x=x,q[cnt].xu=i; } sort(q+1,q+1+cnt,cmp); q[0].x=-1; for (i=1;i<=cnt;i++) { if (q[i].x!=q[i-1].x) a[++tot]=0; newq[tot]=q[i].x;add(tot,q[i].xu); } l=1;kind=0; for (i=1;i<=tot;i++) { for (j=a[i];j;j=ed[j].next) { u[ed[j].col]++; if (u[ed[j].col]==1) kind++; } f=true; while (f&&kind==k&&l<i) { for (j=a[l];j;j=ed[j].next) { u[ed[j].col]--; if (u[ed[j].col]==0) kind--,f=false; } if (!f) for (j=a[l];j;j=ed[j].next) { u[ed[j].col]++; if (u[ed[j].col]==1) kind++; } else l++; } if (kind==k)ans=min(ans,newq[i]-newq[l]); } printf("%d\n",ans); }
相关文章推荐
- bzoj1293: [SCOI2009]生日礼物 贪心
- bzoj 1293: [SCOI2009]生日礼物
- bzoj 1293: [SCOI2009]生日礼物
- 【bzoj 1293】[SCOI2009]生日礼物
- [bzoj1293][SCOI2009]生日礼物 单调队列优化dp
- 【bzoj 1293】[SCOI2009]生日礼物(乱搞|单调队列)
- bzoj 1293: [SCOI2009]生日礼物 (单调队列)
- bzoj 1293: [SCOI2009]生日礼物
- [BZOJ1293][SCOI2009]生日礼物-堆
- BZOJ1293: [SCOI2009]生日礼物
- 【BZOJ 1293】【SCOI 2009】生日礼物
- [bzoj-1293][SCOI2009]生日礼物 题解
- BZOJ 1293: [SCOI2009]生日礼物
- 【堆】bzoj1293 [SCOI2009]生日礼物
- bzoj 1293: [SCOI2009]生日礼物 STL
- 1293: [SCOI2009]生日礼物 - BZOJ
- bzoj 1293: [SCOI2009]生日礼物【单调队列】
- 【bzoj 1293】[SCOI2009] 生日礼物 指针维护队列
- BZOJ 1293: [SCOI2009]生日礼物【单调队列】
- 【BZOJ】1293 [SCOI2009]生日礼物 (这题有多种解法)