FZU 1894 志愿者选拔[双端队列/单调队列]

写这篇题解前重复一句被很多人说过的话...."一直以为单调队列就是优先队列, 2了....."

然后这题开始用priority_queue, 悲催地TLE了...

科普:

1/ 优先队列, 一般用堆实现, 就是STL里priority_queue那玩意...也就是优化dijkstra时用的那玩意....

用处:  从一堆数里用O(1)的时间找到最优值, 用O(logn)的时间插入.删除最优值等.

2/ 单调队列, 有叫双端队列, 即传说中的deque....它的特点是能够O(1)地在头尾插入或删除. 

用处: deque本身是没有任何单调可言的, 但是我们在从尾部插入新数据的时候, 为了维护队列单调性质, 可言从尾部先pop掉所有不优于新元素的元素. 然后在push_back新元素.

这货手敲就跟普通的queue一样方便, 用数组模拟即可.


能用单调队列来优化的问题, 必须具备一个性质, 就是在你新加入元素之后, 不优于这个新元素的元素都没有存在的必要了.

好了, 这题我们要求的是最大值, 用单调队列, 使index递增, 人品值递减. 为了方便, 我们可以再维护一个FIFO的普通队列, 模拟排队, 顺便来存每个人的人品值, 这样单调队列就可以只存人的序号了.


1/ 手敲版 (1078ms)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "

#define MAXN 1000002

int deq[MAXN];		//伪优先队列(deque双向队列)(序号递增, 值递减),	维护方法是尾端插入, 删除前面值小于它的元素.
int front, tail;		//优先队列的指针

int q[MAXN];		//排队本身是 FIFO队列
int head, end;		//FIFO队列的指针

int main()
{
	int T = Rint();
	while(T--)
	{
		front = tail = 0;
		head = end = 0;
		char buf[10];
		scanf("%s", buf);	//START
		while(scanf("%s", buf) && buf[0]!='E')
		{
			char op  = buf[0];
			if(op=='C')	//in
			{
				scanf("%s", buf);		//NAME
				int t = Rint();
				q[end++] = t;
				while(front<tail && q[deq[tail-1]]<t) tail--;		//尾pop
				deq[tail++] = end-1;	//deq存的是序号
			}
			else if(op=='G')	//out
			{
				head++;
			}
			else	// Query
			{
				if(head<end)
				{
					while(deq[front]<head) front++;	//首pop, deq不会为空
					printf("%d\n", q[deq[front]]);
				}
				else
					puts("-1");
			}
		}
	}
}

2/ STL-deque版(1203ms)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "

struct node { int v, id; };
deque<node> deq;
int front, tail;

int main()
{
	int T = Rint();
	while(T--)
	{
		while(!deq.empty()) deq.pop_back();
		front = tail = 0;

		char buf[10];
		scanf("%s", buf);	//START
		while(scanf("%s", buf) && buf[0]!='E')
		{
			char op  = buf[0];
			if(op=='C')	//in
			{
				scanf("%s", buf);		//NAME
				node t;
				t.id = tail++;
				t.v = Rint();
				while(!deq.empty() && deq.back().v<t.v) deq.pop_back();
				deq.push_back(t);
			}
			else if(op=='G')	//out
			{
				front++;
			}
			else	// Query
			{
				if(front<tail)
				{
					while(deq.front().id<front) deq.pop_front();
					printf("%d\n", deq.front().v);
				}
				else
					puts("-1");
			}
		}
	}
}

3/ STL优先队列版....TLE

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "

#define MAXN 1000002
struct node
{
	node(int i, int vv) { id=i; v=vv;}
	int id, v;
};
bool operator<(node x, node  y)			// STL优先队列是按小于号决定优先级, 越大越优先
{ 
	if(x.v!=y.v)
		return x.v<y.v;			//如果我希望大的先出来, 那只要把小于号重载为对应域的小于
	else return x.id>y.id;
}
priority_queue<node> deq;
//queue<int> q;

int main()
{
	int T= Rint();
	while(T--)
	{
		getchar();		//	'\0'

		char buf[10];
		gets(buf);		//START
		int idx = 0;
		int front = 1, tail=1;
		while(scanf("%s", buf) && buf[0]!='E')
		{
			char op = buf[0];
			if(op == 'C')		//in
			{
				scanf("%s", buf);
				int w = Rint();
				deq.push(node(++idx, w));
				tail++;
			}
			else if(op=='G')	//out
			{
				front++;
			}
			else //	'Q'
			{
				if(front<tail){}
				else { puts("-1"); continue; }
				for(node cur=deq.top(); cur.id<front; )
				{
					deq.pop();
					cur = deq.top();
				}
				printf("%d\n", deq.top().v);
			}
		}
		while(!deq.empty()) deq.pop();

	}
}

发布了179 篇原创文章 · 获赞 5 · 访问量 20万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览