POJ 2051 Argus

本文介绍了一种数据流查询系统的设计方案,该系统能够实时处理连续数据流,并按用户定义的时间间隔返回查询结果。通过使用堆数据结构实现高效查询调度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:

        一个数据流是一种实时的、连续的、有序的数据项。数据流中的内容可以包含传感器数据、英特网流量、金融欺诈、网络拍卖、诸如网页访问记录或电话记录等的事物记录数据。可以在这种动态数据流上建立查询,每个一段时间查询一次并返回相应的结果,例如一个工厂仓库的温度探测系统可以这样建立查询:

                每隔5分钟返回一次过去5分钟的内的最高温度;

                返回过去10分钟内每隔楼层的平均温度;

         现需要开发一个类似的数据流查询系统Argus,用户可以通过该系统对数据流建立查询,并按照其想要的时间间隔不断返回相应的结果,比如可以建立如下查询:

                 Register Q_num Period

                 其中Register表示向系统登记查询命令,Q_num为查询的ID号(Q_num ≤ 3000,各ID号不相同),Period为查询的时间间隔(Period ≤ 3000);

         现有多个这样的查询,待登记完毕所有查询后,系统将同时执行所有的命令,现要求前K(K为正整数,K ≤ 10,000)个返回结果的查询ID号,若有多个查询在同一时间点返回结果,则先输出ID号小的那个。

题目链接

注释代码:

/*        
 * Problem ID : POJ 2051 Argus
 * Author     : Lirx.t.Una        
 * Language   : C       
 * Run Time   : 16 ms        
 * Run Memory : 156 KB        
*/

#include <stdio.h>

//maximum number of query,最大查询个数
//最大数为3000,单堆数组中的首个元素不放元素
//下标0可以方便判断指针偏移时是否到达终点(插入操作时)
#define	MAXQUERYN		3001
//命令最大长度为Register的8位,最后一位留给空字符
#define	MAXCMDLEN		9

//对两个查询进行大小比较
//第一种情况是前者的返回时间大于后者
//第二种情况是前者的返回时间等于后者,但前者的ID号大于后者
#define	cmp(x,y)	( (x)->t != (y)->t ? (x)->t - (y)->t : (x)->id - (y)->id )

struct	Node;

typedef	struct Node		Query_body;
typedef	struct Node *	Query;

struct	Node {//查询结点

	int		id;
	int		p;
	int		t;
};

Query_body		qb[MAXQUERYN];//query body,查询体的数组,用于保存查询本身的数据
Query			q[MAXQUERYN];//查询二叉堆数组,用于存放查询的指针(指针空间比),
                        //指针占用空间比查询体小很多,在赋值等操作中可以节省时间
int				sz;//堆的大小,在插入过程中需要动态增加

char			cmd[MAXCMDLEN];

void
push(Query eq) {//入堆操作,element query,带插入的查询

	int		n;//none pointer,空穴位置指针
	int		f;//father pointer of none,空穴的父结点的位置指针

	for ( n = ++sz;//先对堆的大小进行拓展,并将空指针指向拓展出来的空穴
	        ( f = n >> 1 ) && cmp( q[f], eq ) > 0;//若空穴的父结点指针上达0则表示已
			                   //偏移到了尽头,可以直接退出循环
			                   //同时父结点必须大于待插入结点时才可以将父结点移
			                     //入空穴内
			      n = f /*移动后,父结点成为了新的空穴,空穴指针要向上偏移*/ )
		q[n] = q[f];//将父结点移入空穴内

	q[n] = eq;//将待插入结点覆盖到空穴中完成插入工作
}

void
down(void) {//将堆顶的返回时间进行更新,跟新后向下调整其位置

	Query	eq;

	int		n;//none pointer
	int		c;//child pointer of none,空穴的孩子的位置指针

	eq = q[1];
	printf("%d\n", eq->id);//取堆顶查询输出其ID号
	eq->t += eq->p;//更新其返回时间

	for ( n = 1;//输出后相当于堆顶元素出堆,即堆顶为空,需要向下调整挪出合适
	            //的位置给更新过的出堆元素
	        ( c = n + n ) <= sz;//c先指向空穴的左儿子,若左儿子都没就意味着
			      //其没有儿子了,即已经偏移到了堆底,到了尽头,可以退出循环
			      n = c /*移动后儿子成为新的空穴,空穴指针需向下偏移*/) {
	
		//如果空穴还有右儿子,则使c指向较小的右儿子
		if ( c < sz && cmp( q[c + 1], q[c] ) < 0 )
			c++;

		if ( cmp( q[c], eq ) > 0 )//若出堆元素比空穴儿子还小则可以直接退出循环
			                  //将出堆元素覆盖给空穴
			break;
		else
			q[n] = q[c];//否则空穴下移
	}

	q[n] = eq;//将出堆元素覆盖到空穴处完成一次向下调整
}

int
main() {

	int		k;
	int		i;

	sz = 0;
	for ( i = 1; scanf("%s", cmd), *cmd != '#'; i++ ) {
	
		scanf("%d%d", &qb[i].id, &qb[i].p);
		qb[i].t = qb[i].p;
		push( qb + i );
	}
	scanf("%d", &k);
	
	while ( k-- )
		down();

	return 0;
}
无注释代码:

#include <stdio.h>

#define	MAXQUERYN		3001
#define	MAXCMDLEN		9

#define	cmp(x,y)	( (x)->t != (y)->t ? (x)->t - (y)->t : (x)->id - (y)->id )

struct	Node;

typedef	struct Node		Query_body;
typedef	struct Node *	Query;

struct	Node {

	int		id;
	int		p;
	int		t;
};

Query_body		qb[MAXQUERYN];
Query			q[MAXQUERYN];
int				sz;

char			cmd[MAXCMDLEN];

void
push(Query eq) {

	int		n;
	int		f;

	for ( n = ++sz; ( f = n >> 1 ) && cmp( q[f], eq ) > 0; n = f )
		q[n] = q[f]

	q[n] = eq
}

void
down(void) {

	Query	eq;

	int		n;
	int		c;

	eq = q[1];
	printf("%d\n", eq->id)
	eq->t += eq->p

	for ( n = 1; ( c = n + n ) <= sz; n = c ) {
	
		if ( c < sz && cmp( q[c + 1], q[c] ) < 0 )
			c++;

		if ( cmp( q[c], eq ) > 0 )
			break;
		else
			q[n] = q[c];
	}

	q[n] = eq;
}

int
main() {

	int		k;
	int		i;

	sz = 0;
	for ( i = 1; scanf("%s", cmd), *cmd != '#'; i++ ) {
	
		scanf("%d%d", &qb[i].id, &qb[i].p);
		qb[i].t = qb[i].p;
		push( qb + i );
	}
	scanf("%d", &k);
	
	while ( k-- )
		down();

	return 0;
}

STL priority_queue:

/*         
 * Problem ID : POJ 2051 Argus 
 * Author     : Lirx.t.Una         
 * Language   : C++        
 * Run Time   : 16 ms         
 * Run Memory : 208 KB         
*/  

#include <iostream>
#include <cstdio>
#include <queue>

#define	MAXCMDLEN		9

using namespace std;

struct	Qry {

	int		id;
	int		p;
	int		t;

	Qry(void) {}

	Qry( int xid, int xp, int xt ) :
		id(xid), p(xp), t(xt) {}

	bool
	operator<(const Qry &oth) 
	const {

		if ( t != oth.t )	
			return t > oth.t;
		else
			return id > oth.id;
	}
};

char	cmd[MAXCMDLEN];

int
main() {

	int		id, p;
	int		k;

	Qry		q;
	priority_queue<Qry>		heap;

	while ( scanf("%s", cmd), *cmd != '#' ) {
	
		scanf("%d%d", &id, &p);
		heap.push( Qry( id, p, p ) );
	}
	scanf("%d", &k);
	while ( k-- ) {
	
		q = heap.top();
		heap.pop();
		q.t += q.p;
		printf("%d\n", q.id);
		heap.push(q);
	}

	return 0;
}

单词解释:

Argus:人名,希腊神话中的百眼巨人

stream:n, 流,溪流

real-time:adj, 实时的,接到指示立即执行的

continuous:adj, 连续不断的

ordered:adj, 有序的

item:n, 项目,条款,物件

sensor:n, 传感器

traffic:n, 交通,通信量

Internet traffic:n, 英特网通信量

financial:adj, 金融的,财政的

tricker:n, 欺诈者

auction:n, 拍卖

transaction:n, 交易

log:n, 记录,日志

transaction log:n, 交易记录

likewise:adv, 同样地(句首)

query:n, vt, 查询

query over...:vt, 在...上查询

increment:n, 增量

incrementally:adv, 递增地

detection:n, 探测

warehouse:n, 仓库

retrieve:vt, 取回,检索

register:vt, 注册,登记

corresponding:adj, 相应的

desired:adj, 渴求,渴望的,想得到的

instruction:n, 命令,指令

interval:n, 间隔

consecutive:adj, 连贯的,连续的

comfirm:vt, 确认

It is confirmed that..:可以确定的是....

ascending:adj, 上升的,升序的

descending:adj, 下降的,降序的

exceed:vt, 超过

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值