540 - Team Queue | 6740 |
28.95%
|
1465 |
77.13%
|
题目链接:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=103&page=show_problem&problem=481
题目类型: 数据结构, 二叉树
样例输入:
2 3 101 102 103 3 201 202 203 ENQUEUE 101 ENQUEUE 201 ENQUEUE 102 ENQUEUE 202 ENQUEUE 103 ENQUEUE 203 DEQUEUE DEQUEUE DEQUEUE DEQUEUE DEQUEUE DEQUEUE STOP 2 5 259001 259002 259003 259004 259005 6 260001 260002 260003 260004 260005 260006 ENQUEUE 259001 ENQUEUE 260001 ENQUEUE 259002 ENQUEUE 259003 ENQUEUE 259004 ENQUEUE 259005 DEQUEUE DEQUEUE ENQUEUE 260002 ENQUEUE 260003 DEQUEUE DEQUEUE DEQUEUE DEQUEUE STOP 0
样例输出:
Scenario #1 101 102 103 201 202 203 Scenario #2 259001 259002 259003 259004 259005 260001
题目大意:
有个所谓的team排序, 给出t个队伍,以及这些队伍的成员。 然后进行排队。
ENQUEUE x: 把x插入队列中时。如果队列没有该元素的队员,则插入队列的最后面。如果队列中已经有了他的队员,那么插入最后一个队员之后。
DEQUEUE: 把队头的元素删除,并且输出
STOP: 停止
解题思路:
如果对链表熟悉,要模拟这个过程并不难。 STL 中的list挺好用的, 是双向循环链表。 end()成员函数返回链接首位的那个迭代其。 题目的一个关键过程是进行查询元素x时属于哪个队伍(可以用二分查找加速, 提高的速度很客观),还可以开一个超大的数组,用坐标映射元素值,数组保存队伍号,这样的话查找元素的队伍只需要O(1)的时间,是最快的。 然后更关键的一步是,每次插入位置的查找,如果每次的插入都要进行查找一次位置,肯定会TLE。可以另外开一个迭代器数组保存某队伍在队列中的最后一个位置的迭代器。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<list> #include<string> #include<algorithm> using namespace std; int t, commandNum,posTeam; int team[1005][1005]; char command[10]; list<int>m_list; list<int>::iterator lastIt[1005]; int ele[1000000]; // 用来来映射元素属于哪个队伍。下标对应元素值 // 查找这个数在哪个队伍。 int SearchTeam(int num){ int i,j; for(i=0; i<t; ++i){ // 二分查找 if(binary_search(team[i]+1, team[i]+1+team[i][0], num)) return i; } //如果查不到,返回-1. 其实题目给的元素一定时属于某一队的,是我想复杂了 return -1; } void Input(){ int i,j; for(i=0; i<t; ++i){ scanf("%d", &team[i][0]); for(j=1; j<=team[i][0]; ++j){ scanf("%d",&team[i][j]); ele[team[i][j]] = i; } lastIt[i] = m_list.end(); // 进行排序,为二分做准备 sort(team[i]+1, team[i]+1+team[i][0]); } } // 入队 void Enqueue(int num){ posTeam=SearchTeam(num); // 用下面这种的方法获得队伍速度更加快 //posTeam = ele[num]; if(lastIt[posTeam] == m_list.end()){ // 在m_list.end()中插入,效果和push_back一样 lastIt[posTeam] = m_list.insert(lastIt[posTeam], num); } else{ ++lastIt[posTeam]; lastIt[posTeam] = m_list.insert(lastIt[posTeam], num); } } void Dequeue(){ if(m_list.empty()) return; printf("%d\n", m_list.front()); list<int>::iterator it = lastIt[m_list.front()]; // 如果弹出的那个元素是队列中剩下的队伍中的最后一个,要相应的修改 for(int i=0; i<t; ++i){ if(lastIt[i]==m_list.begin()){ lastIt[i] = m_list.end(); break; } } m_list.pop_front(); } void Solve(){ if(!m_list.empty()) m_list.clear(); while(~scanf("%s",command)){ if(!strcmp(command, "STOP")) break; if(!strcmp(command,"ENQUEUE")){ scanf("%d",&commandNum); Enqueue(commandNum); } else if(!strcmp(command,"DEQUEUE")){ Dequeue(); } } } int main(){ freopen("input.txt","r",stdin); int cas=1; while(~scanf("%d",&t) && t){ Input(); printf("Scenario #%d\n", cas++); Solve(); printf("\n"); } return 0; }