BZOJ 1293 SCOI2009 生日礼物 堆

题目大意:给定一个数轴上n个点,每个点有一种颜色,一共k种颜色,求一个最短的区间,包含所有k种颜色

卡了一段时间0.0 一开始想二分答案啥的 后来发现数据范围太大写不了0.0 后来去找题解才发现尼玛真巧妙

维护一个堆 将每种颜色的第一个珠子加入堆 然后不断把最左侧的珠子取出,加入该种颜色的下一个 同时更新ans

果然这么大数据范围还是要用堆这种常数小的数据结构啊0.0

我手写了堆却开了STL的queue 0.0 不要说我有病我只是不习惯STL的堆罢了

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> abcd;
int n,m,k,top,ans=0x7fffffff,maxnum=0;
abcd heap[70];
queue<int>q[70];
void Insert(abcd x)
{
	heap[++top]=x;
	int t=top;
	while( t>1 && heap[t]<heap[t>>1] )
		swap(heap[t],heap[t>>1]),t>>=1;
}
void Pop()
{
	heap[1]=heap[top--];
	int t=2;
	while(t<=top)
	{
		if( t<top && heap[t+1]<heap[t] )
			++t;
		if(heap[t]<heap[t>>1])
			swap(heap[t],heap[t>>1]),t<<=1;
		else
			break;
	}
}
int main()
{
	int i,j,x;
	cin>>n>>k;
	for(i=1;i<=k;i++)
	{
		scanf("%d",&m);
		for(j=1;j<=m;j++)
			scanf("%d",&x),q[i].push(x);
		Insert(abcd(q[i].front(),i));
		maxnum=max(maxnum,q[i].front());
		q[i].pop();
	}
	ans=min(ans,maxnum-heap[1].first);
	while(1)
	{
		abcd temp=heap[1];Pop();
		if(q[temp.second].empty())
			break;
		Insert(abcd(q[temp.second].front(),temp.second));
		maxnum=max(maxnum,q[temp.second].front());q[temp.second].pop();
		ans=min(ans,maxnum-heap[1].first);
	}
	cout<<ans<<endl;
	return 0;
}
时间: 2024-10-12 12:20:34

BZOJ 1293 SCOI2009 生日礼物 堆的相关文章

BZOJ 1293: [SCOI2009]生日礼物 贪心

1293: [SCOI2009]生日礼物 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2513  Solved: 1370[Submit][Status][Discuss] Description 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置).某些坐标上可以没有彩珠,但多个彩珠也可以出现在同一个位置上. 小布生日快到了,于是小西打算剪一段彩带送给小

bzoj 1293: [SCOI2009]生日礼物

Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1559  Solved: 848[Submit][Status][Discuss] Description 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置).某些坐标上可以没有彩珠,但多个彩珠也可以出现在同一个位置上. 小布生日快到了,于是小西打算剪一段彩带送给小布.为了让礼物彩带足够漂亮,小西希望这一段彩

bzoj 1293: [SCOI2009]生日礼物【单调队列】

一开始用了复杂度看起来对实则常数巨大的线段树+hash--后来发现队列就行-- 把珠子按位置排序,然后用队列维护一段,枚举右端点更新答案即可 #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N=1000005,inf=2147483647; int n,m,s[65],ans=inf,tot,sum,l=1,r; struct qwe { int

1293: [SCOI2009]生日礼物

1293: [SCOI2009]生日礼物 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1096  Solved: 584[Submit][Status] Description 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置).某些坐标上可以没有彩珠,但多个彩珠也可以出现在同一个位置上. 小布生日快到了,于是小西打算剪一段彩带送给小布.为了让礼物彩带足

1293: [SCOI2009]生日礼物 - BZOJ

Description 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置).某些坐标上可以没有彩珠,但多个彩珠也可以出现在同一个位置上. 小布生日快到了,于是小西打算剪一段彩带送给小布.为了让礼物彩带足够漂亮,小西希望这一段彩带中能包含所有种类的彩珠.同时,为了方便,小西希望这段彩带尽可能短,你能帮助小西计算这个最短的长度么?彩带的长度即为彩带开始位置到结束位置的位置差.Input 第一行包含两个整数N,

bzoj1293[SCOI2009]生日礼物 尺取法

1293: [SCOI2009]生日礼物 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2838  Solved: 1547[Submit][Status][Discuss] Description 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置).某些坐标上可以没有彩珠,但多个彩珠也可以出现在同一个位置上. 小布生日快到了,于是小西打算剪一段彩带送给小

矩阵乘法专题1——bzoj 1297 [SCOI2009] 迷路题解

题目链接 题意:给两个长度分别为n和m的序列,现在有两种操作:1.分别选择两个序列的一个非空前缀,切两个前缀的最后一位相同,删除之,得到1分(只累计),消耗e:2.直接删除两个序列,消耗值定于两个序列之前删除的元素个数之和,并且使得得到的分有效(之前没有有效分) 分析: 首先,问题其实就是转化成,进行若干次操作1,然后进行操作2 还要找到一个判别标准,来评判较优的状态(贪心) 每次的消耗值比较大,其实可以计算出最大的删除次数,这个值不是很大 状态表示: 简单的,一个状态可以表示为串A的位置.串B

BZOJ 1296: [SCOI2009]粉刷匠

BZOJ 1296: [SCOI2009]粉刷匠 Description windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色. 每个格子最多只能被粉刷一次. 如果windy只能粉刷 T 次,他最多能正确粉刷多少格子? 一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷. Input 输入文件paint.in第一行包含三个整数,N M T. 接下来有N行,每行一个长度为M的字符串,

BZoj 1293 生日礼物(小顶堆)

传送门:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27400 Anayse:小顶堆: 1 1 5     - >    1 3 5     ->    3 5 7    ->     5 7 8 pop(1)    p(1)      p(3)       最优解. 每次剔除堆顶,然后换push与堆顶相同种类的珠子,由于单调,,距离会被缩短,于是找出最优解.详见上式. push()  log(n) so,复杂度