PAT Note

include头文件可以使用#include<bits/stdc++.h>替代

代码截图摘自柳婼

1003.

急救,找到最短路径,最短路径的条数,并找到最短路径一路上的点权和

使用dijkstra算法:

声明数组e[510][510] 邻接矩阵用于表明结点之间的连接情况;

在最开始时,将邻接矩阵赋值为极大值。

 

将起点的dis[c1]赋值为0后,在第一次处理中,肯定是起始结点是最小值,将起点在visit中的索引设置为true,判断剩余的所有节点,如果结点没有被访问过,且结点之间的距离非无穷大,则更新dis[u]结点的距离。实际上就是更新所有与起点邻接的点。

下一次则找没有访问过的,最近的结点,将其visit的索引设置为true,然后更新这个结点的所有邻接结点的dis值。

  1. 找到没有访问过的 dis最小的结点
  2. 将该节点的visit设置为true,标记访问过;
  3. 将该节点的所有邻接结点的距离更新;
  4. 跳回步骤1

1013.battel over cities

一堆城市,城市之间有高速公路连接,如果一个城市被占领,至少需要几条高速公路将城市连接起来。

解决方法:将问题转化为连通域分量问题,如果有a个连通分量,则只需要修a-1个高速公路即可连接起来

  1. 将相邻的城市读入邻接矩阵,将相邻的矩阵的值设置为1;
  2. 将所有城市的visit矩阵设置为false,将被占领的城市的访问设置为true,这样这个城市就不会被访问了

对每个结点调用dfs,每个dfs会将所有与当前结点连接的结点的访问设置为ture,一共调用了几次dfs,即有几个联通分量。

  1. dfs

 

1018.

公共自行车管理,要求将目标点的自行车数量改为平衡,一路上可以带去自行车,回来的时候可以把自行车带回

找出最短路径,如果有多条相同的最短路径,则找出需要带去或者带回自行车数量最少的路径

  1. 调用dijkstra算法,得到从根结点开始到所有节点的最短路径;此时注意维护vector数组vector<int> pre[510],其中每一个vector标志了当前结点之前的所有最短前驱结点;

  1. 调用dfs算法,从需要调整的结点开始(不是从根节点自行车管理委员会办事处),根据前驱结点的vector pre数组,依次向前dfs,并一路上记录need和back,根据need 和back的大小,每次在到达自行车管理处时都比较一次,如果当前更小,则更新path

示意图:

当所有访问到根节点的路径被遍历后,仿真结束。

1021.

Deepest Root

判断图是否是一颗树,如果是树的话,找出最深的根

这里采用了建立vector元素类型的vector方法:

vector<vector<int>> v;

调用v[a].push_back(b);v[b].push_back(a);将图描述。

  1. 在for循环中循环调用dfs

得到的temp就是当使用一个结点时,得到的最深的根的vector,将它们存放到set中,cnt为联通分量的计数。

  1. dfs看上去还是比较简单的,每访问一个,标记一个,通过图的vector,循环多次调用dfs

  1. 在进行一次处理,最深的根节点的集合就是,分别以两个节点,做两次dfs,取结果的并集,就是最深根节点的集合。

1034. Head of Gang

输入一系列的人的联系以及边权,统计有多少个黑帮,边权最大的人就是头目

本质上就是连通分量的统计

连通分量的统计方式使用dfs,一个图做了多少次dfs就有多少次连通分量。

注意:在做dfs时,每扫描过一节点,就将该节点设置为已访问过,或者修改邻接矩阵,将邻接矩阵的权重改为0.

小技巧是这里使用了引用,在每个dfs递归函数中都能修改引用的参数。

dfsTrave遍历矩阵,做过多少次dfs就有少个邻接矩阵

1111. Online Map

给出n个节点对之间的时间距离与路程距离,求给定点到目标点之间的最短距离与最短路径

解题思路:

首先建立邻接矩阵,将节点对之间的关系存入邻接矩阵

调用dijkstra算法,求出结点到目标节点之间的最短时间距离;

调用递归函数,根据dispre[]前驱结点数组找出最终的路径,存入dispath中

调用dijkstra算法,求出结点到目标节点之间的最短长度距离;

调用递归函数,根据dispre[]前驱结点数组找出最终的路径,存入dispath中

如何实现dijkstra算法呢?

如果一共有x个节点,那么最外层最多x个循环

初始化dis[x]数组为极大值,起点对应的数组项为0,

for(n 1:x)

找出未访问过的节点中dis最小的;

将该节点设置为已访问;

                   for(n 1:x)

如果经过该节点到达其邻接结点的距离更小,则

将该节点的邻接结点的距离更新,同时更新前驱结点数组。

递归函数根据目标结点一直追到始发点:

 

1127.

习惯声明的是vector<int> data[50],声明一个vector类型的数组,数组大小为50,其中每一个元素是vector类型的;

树的形式可以用tree[50][2]来表示,即共有50个节点,每个结点的0表示左儿子,1表示右儿子;

根据中序和后序建树:

注意:index使用引用传递,实际上index就是结果,最终递归建立一颗完整的树;

这里的index也仅仅是index,应当是1,2,3,4的序号,这个需要是按照后序来的。

广度优先搜索 bfs:

之前考虑过广度优先搜索如何区分不同的熟悉怒,实际上如果在向队列入队的时候就压入的是结构体类型的node,在node的结构体中将depth深度在入队时就进行累加,那么在出对时,自然就能区分出不同的深度。

根据出队的temp.depth存入vector数组类型的result中。

最后逐层打印:

步骤:建tree,tree中包含结点顺序;广度优先搜索得到result;打印

1147.

判断是最大堆还是最小堆,并后续遍历打印:

首先声明全局的vector变量,在scanf得到vector的大小后,调用v.resize(n)调整为n的大小。

在循环中判断m个序列,每个序列在for((n-1)/2)循环中依次判断左,右。

最后调用后续遍历,由于是完全二叉树,只需要递归索引即可,注意是在postOrder左右两颗树后,打印。

(c++题解,代码运行时间小于200ms,内存小于64MB,代码不能有注释)It’s time for the company’s annual gala! To reward employees for their hard work over the past year, PAT Company has decided to hold a lucky draw. Each employee receives one or more tickets, each of which has a unique integer printed on it. During the lucky draw, the host will perform one of the following actions: Announce a lucky number x, and the winner is then the smallest number that is greater than or equal to x. Ask a specific employee for all his/her tickets that have already won. Declare that the ticket with a specific number x wins. A ticket can win multiple times. Your job is to help the host determine the outcome of each action. Input Specification: The first line contains a positive integer N (1≤N≤10 5 ), representing the number of tickets. The next N lines each contains two parts separated by a space: an employee ID in the format PAT followed by a six-digit number (e.g., PAT202412) and an integer x (−10 9 ≤x≤10 9 ), representing the number on the ticket. Then the following line contains a positive integer Q (1≤Q≤10 5 ), representing the number of actions. The next Q lines each contain one of the following three actions: 1 x: Declare the ticket with the smallest number that is greater than or equal to x as the winner. 2 y: Ask the employee with ID y all his/her tickets that have already won. 3 x: Declare the ticket with number x as the winner. It is guaranteed that there are no more than 100 actions of the 2nd type (2 y). Output Specification: For actions of type 1 and 3, output the employee ID holding the winning ticket. If no valid ticket exists, output ERROR. For actions of type 2, if the employee ID y does not exist, output ERROR. Otherwise, output all winning ticket numbers held by this employee in the same order of input. If no ticket wins, output an empty line instead. Sample Input: 10 PAT000001 1 PAT000003 5 PAT000002 4 PAT000010 20 PAT000001 2 PAT000008 7 PAT000010 18 PAT000003 -5 PAT102030 -2000 PAT000008 15 11 1 10 2 PAT000008 2 PAT000001 3 -10 1 9999 1 -10 3 2 1 0 3 1 2 PAT000001 3 -2000 Sample Output: PAT000008 15 ERROR ERROR PAT000003 PAT000001 PAT000001 PAT000001 1 2 PAT102030
08-12
<think>We are going to solve the problem in C++ with the following steps: 1. We have up to 100 queries of type 2 (by employee ID) and up to 10^5 tickets and 10^5 queries. 2. We note that the employee IDs are strings of the form "PATxxxxxx", and there are up to 10^5 tickets, so we can have duplicate employee IDs (same employee can have multiple tickets). Requirements: - For action "1 x": We need to find the smallest ticket number >= x. If found, output the employee ID of that ticket. Otherwise, output "ERROR". - For action "2 y": We output all winning ticket numbers for employee y in the order of input (if the employee doesn't exist, output "ERROR"; if no winning ticket, output empty line). - For action "3 x": We output the employee ID of the ticket with number x. If no such ticket, output "ERROR". Important: A ticket can win multiple times. But note: the same ticket number might appear multiple times? The problem says "each ticket has a unique integer", so each ticket number is unique. However, note: the same employee can have multiple tickets (with different numbers). And the same ticket (by number) cannot be repeated. Approach: We have two main challenges: 1. Efficiently answering the "1 x" and "3 x" queries which require looking up by ticket number. 2. For the "2 y" queries, we have to output the winning tickets for an employee in the order of input. Since there are at most 100 queries of type 2, we can do the following: We will store: - A mapping from ticket number to employee ID (for unique tickets, so we can do a direct lookup for type 3 and also for type 1 we need the employee). - For type 1 queries: we need to quickly find the smallest ticket number >= x. We can use a sorted set (or set) and then use lower_bound. However, note: we have to consider that the same ticket number might be declared as winner multiple times? But the problem says "a ticket can win multiple times", but note that the same ticket number is unique. So when we look for the ticket, we are looking for the ticket number that exists. Steps: 1. We read N, then N lines of (employee_id, ticket_number). 2. We note: we have to preserve the order of tickets for each employee? Only for the output in type 2: we are to output in the same order as input. But note: the input order of tickets for an employee might be scattered. However, the problem says: "output all winning ticket numbers held by this employee in the same order of input". So we need to record for each employee, the list of tickets (the ticket numbers) that they have, in the order they appear in the input. But also, we need to mark which of these tickets have won. How about: - We create a global vector that records the entire input? But we have 10^5 tickets, and then for each employee we want to output the winning ones in the order of input. - Alternatively, we can store for each employee, a vector of pairs (ticket_number, won_count) but note: we don't need the count, we need to output the ticket number every time it wins? But the problem says "all his/her tickets that have already won". And since a ticket can win multiple times, we have to record each win? However, note the problem: "Declare that the ticket with a specific number x wins." -> then we mark that ticket as having won. But the problem says "a ticket can win multiple times", meaning the same ticket can be declared winner multiple times? Then for an employee, we want to output the same ticket number multiple times? But the output for type 2: we are to output the winning ticket numbers. The problem says: "output all winning ticket numbers held by this employee in the same order of input". Interpretation: - If a ticket wins multiple times, then for the employee, we should output that ticket number multiple times? But note: the problem says "ticket numbers", and the same ticket number is printed multiple times? However, the sample input does not show multiple wins for the same ticket. But the problem says "a ticket can win multiple times", so we must account for that. How to record wins per ticket? We can have: - We maintain a set (or map) for the winning events? But note: the type 2 query asks for all winning tickets (by the employee) that have ever won (and if won multiple times, then we output the ticket number multiple times?). However, the problem does not specify the order of multiple wins. But the output order is defined as the same order as input. So we are to output the ticket numbers in the order that the tickets were originally input? And if the same ticket wins multiple times, then each win event should be recorded? But the problem says "all his/her tickets that have already won" - meaning that the ticket has won at least once? Then we output the ticket number once for each win event? Or one time per win event? Let me read the problem again: "output all winning ticket numbers held by this employee in the same order of input" This is ambiguous. But note: the sample does not have multiple wins for the same ticket. However, the problem states: "a ticket can win multiple times", so we must output the ticket number multiple times? But the problem says "in the same order of input". The input order of what? The tickets. So if an employee has two tickets: [1, 2] in that order. Then if ticket 1 wins twice and ticket 2 wins once, then the output should be: 1, 1, 2? or 1, 2? The problem says: "all winning ticket numbers" and then "in the same order of input". It likely means: for each ticket (by the input order) that has won at least once, we output the ticket number? But then what about multiple wins? However, note: the problem says "ticket numbers", and each win event is for a specific ticket. But the type 2 query does not specify an event, it just asks for the employee's winning tickets. The sample output for type 2: 2 PAT000008 -> outputs 15 2 PAT000001 -> outputs (empty) then later after wins, outputs "1 2" After the wins: 3 1 -> wins, then 2 PAT000001 outputs "1 2" But note: the employee PAT000001 has two tickets: 1 and 2. Both have won at least once? Then we output the ticket numbers in the order of input: first ticket 1, then ticket 2? So we output "1 2" (on the same line? but the sample output has two numbers: "1 2" meaning two numbers?). However, the sample output for the last query: 2 PAT000001 outputs: 1 2 So it's two numbers. But note: the employee has two winning tickets: 1 and 2, each won at least once. And we output the ticket numbers in the order of the input (the first ticket of PAT000001 is 1, then the second is 2). We do not output the same ticket number multiple times even if it won multiple times? The problem says: "all winning ticket numbers" - meaning each distinct winning ticket? Or every win event? But the sample: The employee PAT000001 has two tickets: 1 and 2. Both have won. So we output both. And the output is "1 2", meaning two numbers. So it seems we are to output each distinct winning ticket (by its number) that the employee has, and we output them in the order of the input (the order in which the tickets were given to the employee in the input). And if the same ticket wins multiple times, we still output the ticket number only once? However, the problem says: "a ticket can win multiple times", but then the type 2 query does not ask for the win events, it asks for the tickets that have won. So if a ticket has won at least once, we list it once. Therefore, for each employee, we want to record the set of distinct ticket numbers that have won? But then we have to output in the order of input. How? We can do: - We create a mapping: employee_id -> vector of all ticket numbers that belong to this employee (in the order of input). But then we also need to know which of these tickets have won at least once. - Alternatively, we can record for each employee, a vector of pairs: (ticket_number, has_won) and then update has_won when a win occurs. But then when we output, we traverse the vector and output the ticket_number for which has_won is true. But note: if we update the same ticket multiple times, we set has_won to true and then we don't change it. So we only output once. - However, the problem says: "a ticket can win multiple times" but we are only required to output the ticket number once? That seems consistent with the sample. So we will: - Have a global set (or sorted container) for the tickets for quick lookup by number: we want to map ticket number to employee ID and also for the type 1 query we need to find the smallest ticket >= x. - We also need to record the wins per ticket? Actually, we don't need the count of wins, we just need to know that the ticket has won at least once? Because for type 2 we only output the ticket number once. - But note: the problem says "Declare that the ticket with a specific number x wins." and we are to record that win. However, for type 2 we are only asked for the tickets that have won (at least once). So we can mark a boolean for the ticket: has_won. Implementation: Let: - `ticketOwner`: a map from ticket_number to employee_id (string). But note: the same ticket number is unique. - `employeeTickets`: a map from employee_id to a vector of the ticket numbers that employee has (in the order of input). But we also want to mark which ones have won? Alternatively, we can have a separate set for winning tickets? Or we can have a set for winning tickets? However, for type 2: we need to output the winning tickets for an employee in the order of input. So: We can have: map<string, vector<long long>> employeeTickets; // employee_id -> list of ticket numbers (in input order) set<long long> winningTickets; // to record which tickets have won at least once? Actually, we don't need the entire set, we only need to know per employee. But we can also update per employee. Alternatively, we can have a boolean flag per ticket? But we have 10^5 tickets, and then for each employee we traverse the vector and check if the ticket is in a global winning set? That would be O(n) per type 2 query, and we have at most 100 such queries, so worst-case 100 * (number of tickets per employee) which might be 100 * (max tickets per employee). The total tickets is 10^5, so worst-case an employee has 10^5 tickets. Then 100*10^5 = 10^7, which is acceptable. But note: we are storing the vector of tickets per employee. We can also have: map<string, vector<long long>> employeeTickets; // all tickets of the employee (in order) set<long long> globalWinningTickets; // set of all tickets that have won at least once. Then for a type 2 query for employee y: if employeeTickets does not have y, output "ERROR" else, traverse the vector of tickets for y, and for each ticket, if it is in globalWinningTickets, then output it? But we have to output in the order of the vector (which is the input order). And we output each winning ticket only once (even if it won multiple times, we only mark it as won). But note: the problem says "a ticket can win multiple times", but we are only outputting the ticket number once. So that matches. Steps for actions: Type 1: "1 x" We need to find the smallest ticket number >= x that exists. We can maintain a sorted set (or multiset) of all ticket numbers? But note: the tickets are unique, so set is enough. Let `ticketSet` be a set<long long> of all ticket numbers. Then: auto it = ticketSet.lower_bound(x); if (it == ticketSet.end()) -> output "ERROR" else -> output the employee_id for ticket *it. We have a map: ticketToOwner[*it] (which we can precompute). Type 2: "2 y" If employeeTickets.find(y) == employeeTickets.end() -> "ERROR" Else: vector<long long> tickets = employeeTickets[y]; for each ticket in tickets: if (globalWinningTickets.find(ticket) != globalWinningTickets.end()) then output the ticket (with a space separator? but the problem says output the numbers in the same line, space separated? and if none, output empty line) But note: we must output the numbers in the order of the vector. However, the problem says: output the winning ticket numbers. We must output them in the order of input. And the vector is in the order of input. Type 3: "3 x" If the ticket x exists? Check in ticketSet? Actually, we have a map from ticket number to employee ID: ticketToOwner. If ticketToOwner.find(x) == ticketToOwner.end() -> "ERROR" Else -> output ticketToOwner[x] Also, we must mark that ticket x has won? So we add x to globalWinningTickets? But note: what if the same ticket wins again? Then we mark it again? But we are using a set, so duplicate adds are ignored. That's what we want: we only care that it has won at least once. However, note: the problem says "a ticket can win multiple times", but for type 2 we only output the ticket once. So we don't need to record the count. But wait: what about type 1? When we do a type 1, we also mark the winning ticket? Actually, the problem says: Action 1: "Announce a lucky number x, and the winner is then the smallest number that is greater than or equal to x." -> we must mark that ticket as having won? Action 3: "Declare that the ticket with a specific number x wins." So both action 1 and action 3 declare a winner. Therefore, after we find the ticket in action 1, we must mark that ticket as having won (by adding to globalWinningTickets). However, note: the problem says "For actions of type 1 and 3, output the employee ID holding the winning ticket." and then we mark the ticket as won? Therefore, we must update globalWinningTickets in both action 1 and action 3. Steps for action 1: - Find the ticket number t (smallest >= x) in the set of tickets. - If found, output the employee ID for t. - Then mark t as won: globalWinningTickets.insert(t); - If not found, output "ERROR" Steps for action 3: - If the ticket x exists, output the employee ID and then mark x as won: globalWinningTickets.insert(x); - Else, output "ERROR" But note: what if the same ticket is declared winner again? Then we mark it again? But globalWinningTickets is a set, so duplicate inserts are harmless. However, we must note: the problem says "a ticket can win multiple times", but we are only storing that it has won at least once. That is sufficient for the type 2 output. Implementation details: We need: set<long long> ticketSet; // all ticket numbers map<long long, string> ticketToOwner; // maps ticket number to employee ID set<long long> globalWinningTickets; // tickets that have won at least once map<string, vector<long long>> employeeTickets; // for each employee, the list of ticket numbers (in input order) How to build employeeTickets? When reading the input, for each line (employee_id, ticket_number): ticketSet.insert(ticket_number); ticketToOwner[ticket_number] = employee_id; employeeTickets[employee_id].push_back(ticket_number); Note: the employee_id is given as a string. We assume the same employee_id string for the same employee. However, note: the problem says "employee ID in the format PAT followed by a six-digit number", so they are strings. But caution: what if the same ticket number appears twice? The problem says "each of which has a unique integer", so no duplicate. Then we process Q queries. For each query: if type == 1: long long x; auto it = ticketSet.lower_bound(x); if (it == ticketSet.end()) { cout << "ERROR\n"; } else { long long ticket = *it; cout << ticketToOwner[ticket] << '\n'; globalWinningTickets.insert(ticket); // mark as won } if type == 2: string y; // read y if (employeeTickets.find(y) == employeeTickets.end()) { cout << "ERROR\n"; } else { vector<long long> tickets = employeeTickets[y]; vector<long long> wins; for (auto t : tickets) { if (globalWinningTickets.find(t) != globalWinningTickets.end()) { wins.push_back(t); } } // Now output the wins: if wins is empty, output an empty line? // Otherwise, output the wins in the order of the vector (which is the input order) and space separated? for (int i = 0; i < wins.size(); i++) { if (i > 0) cout << ' '; cout << wins[i]; } cout << '\n'; } if type == 3: long long x; if (ticketSet.find(x) == ticketSet.end()) { cout << "ERROR\n"; } else { cout << ticketToOwner[x] << '\n'; globalWinningTickets.insert(x); } However, note: the set `ticketSet` is a sorted set. We use it for type 1 and type 3 to check existence? Actually, for type 3 we can use ticketSet.find? But we have a map ticketToOwner, so we can check existence by ticketToOwner.find(x) != ticketToOwner.end()? But note: we built ticketSet and ticketToOwner from the same input. So if a ticket is in ticketSet, it is in ticketToOwner. Alternatively, we can use only ticketToOwner to check existence? Yes. So we can avoid maintaining ticketSet? Actually, no: for type 1 we need lower_bound on the set of tickets. So we need the set. But note: we have a set of all ticket numbers: ticketSet. We can use that for lower_bound. However, we have to update the set? The set is fixed: we read all tickets at the beginning. But what if we have duplicate tickets? The problem says unique, so no. But note: the problem says the ticket numbers are unique. Therefore, we can do: set<long long> ticketSet; // all ticket numbers And we use it for type 1 and type 3? Actually, for type 3 we can also use the set to check existence? But we have ticketToOwner: we can check with ticketToOwner.count(x) or ticketSet.count(x). Both are O(log n). We can use either. However, for type 1 we require the set for lower_bound. Let's code accordingly. But note: the constraints: N, Q up to 10^5. The set operations are O(log n) per operation, so total O((N+Q) * log N) which is acceptable. However, the type 2 queries: we are iterating over the entire list of tickets for an employee. The worst-case employee might have 10^5 tickets, and we have at most 100 type 2 queries, so worst-case 100 * 10^5 = 10^7, which is acceptable. But note: we are building a vector for each employee. The total memory is the total number of tickets (10^5). So we are safe. However, we must be cautious: the employeeTickets map: the key is a string (about 9 characters) and the value is a vector. The total number of employees might be up to 10^5? But the problem says: each employee ID is given. But the same employee can appear multiple times. So the map employeeTickets will have one entry per distinct employee, and the vector for that employee will have all the tickets. Total memory: the vectors: total 10^5 long longs (about 800KB) and the set: 10^5 long longs (about 800KB) and the map: 10^5 entries of (long long -> string) and the string is about 9 bytes? Actually, the string is variable: "PAT000001" is 9 characters. But we store the same employee ID multiple times? In the map employeeTickets, we store the employee ID as the key, and then the vector. The ticketToOwner: each ticket has a string, so 10^5 strings. But each string is the same for the same employee? Actually, we store the same string multiple times. We can avoid that by storing the employee ID as a string and then in the map employeeTickets we use the same string? But the keys in the map are strings, and the values are vectors. Alternatively, we can use a map from string to vector, and for the ticketToOwner, we can store the employee ID as a pointer to the same string? But that is complex. Instead, we can store the employee ID string once in the map and then use a reference? But in C++ we are storing copies. Total memory for strings: Each employee ID is 9 characters (so 9 bytes per string). How many distinct employees? In the worst-case, each ticket belongs to a distinct employee? Then we have 10^5 distinct employees. Then: employeeTickets: 10^5 keys (each 9 bytes) -> 900,000 bytes for keys, and then each vector: the vector itself has a small overhead (about 24 bytes per vector) and then the data: each vector has one or more tickets. The total number of tickets is 10^5, so the total for the vectors is 10^5 * sizeof(long long) = 800,000 bytes. ticketToOwner: 10^5 entries: key is long long (8 bytes) and value is string (9 bytes) -> 10^5 * (8+9) = 1,700,000 bytes. globalWinningTickets: set of long long: 10^5 * 8 = 800,000 bytes? But worst-case we mark all as winning? Then 800,000 bytes. ticketSet: set of long long: 10^5 * 8 = 800,000 bytes? (the set has overhead: each node has pointers, so about 8*3 per node? so 24 bytes per node -> 2,400,000 bytes?). Total: about 900,000 (employeeTickets keys) + 800,000 (employeeTickets vectors data) + 1,700,000 (ticketToOwner) + 800,000 (globalWinningTickets) + 2,400,000 (ticketSet) = about 6.6 MB. Then we have the vectors for employeeTickets: each vector has a small overhead (about 24 bytes per vector) * 10^5 = 2,400,000 bytes -> total about 9 MB. And we have the input and output buffers. So 64 MB is sufficient. But note: the set and map have node-based structures that use more memory. But 10^5 nodes is acceptable. Code without comments (as per requirement) and we must be efficient. Let's code accordingly. Important: The problem says the ticket numbers can be negative and as large as 10^9 in absolute value, so we use long long. Steps: #include <iostream> #include <vector> #include <set> #include <map> #include <cctype> #include <algorithm> #include <string> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); int N; cin >> N; set<long long> ticketSet; map<long long, string> ticketToOwner; set<long long> globalWinningTickets; map<string, vector<long long>> employeeTickets; for (int i = 0; i < N; i++) { string emp; long long x; cin >> emp >> x; ticketSet.insert(x); ticketToOwner[x] = emp; employeeTickets[emp].push_back(x); } int Q; cin >> Q; while (Q--) { int type; cin >> type; if (type == 1) { long long x; cin >> x; auto it = ticketSet.lower_bound(x); if (it == ticketSet.end()) { cout << "ERROR\n"; } else { cout << ticketToOwner[*it] << '\n'; globalWinningTickets.insert(*it); } } else if (type == 2) { string y; cin >> y; if (employeeTickets.find(y) == employeeTickets.end()) { cout << "ERROR\n"; } else { const vector<long long>& tickets = employeeTickets[y]; vector<long long> wins; for (long long t : tickets) { if (globalWinningTickets.find(t) != globalWinningTickets.end()) { wins.push_back(t); } } if (wins.empty()) { cout << '\n'; } else { for (int i = 0; i < wins.size(); i++) { if (i > 0) cout << ' '; cout << wins[i]; } cout << '\n'; } } } else if (type == 3) { long long x; cin >> x; if (ticketSet.find(x) == ticketSet.end()) { cout << "ERROR\n"; } else { cout << ticketToOwner[x] << '\n'; globalWinningTickets.insert(x); } } } return 0; } But note: the problem says "output the employee ID holding the winning ticket" for type 1 and 3. And for type 2, we output the winning ticket numbers (if any) in the order of input. However, the sample input: "1 10" -> we find the smallest ticket >=10: in the sample, the tickets are: [ -2000, -5, 1, 2, 4, 5, 7, 15, 18, 20] The smallest ticket >=10 is 15? But wait: 7 is less than 10, then 15 is the next. The employee for 15 is PAT000008? -> output "PAT000008" Then "2 PAT000008": the employee PAT000008 has two tickets: 7 and 15. And 15 has been marked as won (from the action 1). So we output 15. Then "2 PAT000001": the employee PAT000001 has two tickets: 1 and 2. None has been marked as won? So output empty line? But the sample output for this is empty? Actually, the sample output for this is: PAT000008 15 [empty line?] Then the next outputs: ERROR ERROR ... However, the sample output: PAT000008 15 ERROR ... So the empty line is printed as a blank line. Then the next actions: "3 -10": there is no ticket -10? -> output "ERROR" "1 9999": no ticket >=9999 -> output "ERROR" "1 -10": the smallest ticket >=-10: we have -2000, -5: the smallest >=-10 is -5? -> employee PAT000003 -> output "PAT000003" Then we mark -5 as won. Then "3 2": there is a ticket 2? -> employee PAT000001 -> output "PAT000001", and mark 2 as won. Then "1 0": smallest ticket >=0: we have 1 -> PAT000001 -> output "PAT000001", and mark 1 as won. Then "3 1": ticket 1 exists -> PAT000001 -> output "PAT000001", and mark 1 as won (again, but set ignores). Then "2 PAT000001": now the employee PAT000001 has tickets [1,2]. Both have been won (1 was won by the last two actions? and 2 by the action "3 2"). So we output: first 1 then 2 -> "1 2" Then "3 -2000": exists -> employee PAT102030 -> output "PAT102030", and mark -2000 as won. The sample output: PAT000008 15 ERROR ERROR PAT000003 PAT000001 PAT000001 PAT000001 1 2 PAT102030 But the sample output in the problem is: PAT000008 15 ERROR ERROR PAT000003 PAT000001 PAT000001 PAT000001 1 2 PAT102030 So it matches. However, note: the sample input has 11 queries, so we output 11 lines? Actually: Query 1: "1 10" -> PAT000008 (line1) Query 2: "2 PAT000008" -> 15 (line2) -> then we output a new line? so line2: "15" and then we have a blank line for query3? But the problem output: PAT000008 15 ERROR ... How many lines? Line1: "PAT000008" Line2: "15" Line3: (empty line) -> because the next query is type2 for PAT000001 which has no wins at that time -> output a blank line? Then Line4: "ERROR" But the sample output says: PAT000008 15 ERROR ... That means after the first type2 we output two lines? Actually, the first type2 outputs one line: the winning numbers (if any) and then we output a newline at the end. So for the second query (type2) we output "15" and then a newline? and then the third query (type2) outputs an empty line? Actually, the code for type2: if wins is empty: we output a newline (so an empty line) -> that's one line. else: we output the numbers and then a newline -> one line. So the output for the 11 queries: Query1: type1 -> "PAT000008" (line1) Query2: type2 -> output "15" (without newline? no: we output the numbers and then a newline) -> so line2: "15" Query3: type2 -> output a newline -> line3: empty Query4: type3 -> "ERROR" -> line4 Query5: type1 -> "ERROR" -> line5 Query6: type1 -> "PAT000003" -> line6 Query7: type3 -> "PAT000001" -> line7 Query8: type1 -> "PAT000001" -> line8 Query9: type3 -> "PAT000001" -> line9 Query10: type2 -> "1 2" -> line10 Query11: type3 -> "PAT102030" -> line11 So the output has 11 lines? But the sample output only shows 10 lines? Actually, the sample input has 11 actions, and the sample output has: PAT000008 15 ERROR ERROR PAT000003 PAT000001 PAT000001 PAT000001 1 2 PAT102030 That's 10 lines? But note: the second query (type2) outputs one line: "15", and the third query (type2) outputs an empty line -> that's two lines. Then the rest: 9 lines? total 11 lines. The problem says: Sample Output: PAT000008 15 ERROR ERROR PAT000003 PAT000001 PAT000001 PAT000001 1 2 PAT102030 How many lines? Line1: PAT000008 Line2: 15 Line3: (empty) Line4: ERROR Line5: ERROR Line6: PAT000003 Line7: PAT000001 Line8: PAT000001 Line9: PAT000001 Line10: 1 2 Line11: PAT102030 So 11 lines. But the problem sample output is written as 10 lines? Actually, the blank line is represented as a blank line. So the output is: PAT000008 15 [blank] ERROR ERROR ... So the sample output in the problem has 11 lines? They just show the blank as an empty line. Therefore, the code is as above. Let me run the sample input with the code to see if it matches. However, note: the sample input has: PAT000001 1 PAT000003 5 PAT000002 4 PAT000010 20 PAT000001 2 PAT000008 7 PAT000010 18 PAT000003 -5 PAT102030 -2000 PAT000008 15 Then the queries: 11 1 10 2 PAT000008 2 PAT000001 3 -10 1 9999 1 -10 3 2 1 0 3 1 2 PAT000001 3 -2000 We have: ticketSet: [-2000, -5, 1, 2, 4, 5, 7, 15, 18, 20] Query1: 1 10 -> lower_bound(10) -> first element >=10: 15 -> employee PAT000008 -> output "PAT000008", and mark 15 as won. Query2: 2 PAT000008 -> employeeTickets["PAT000008"]: [7,15] -> wins: 15 -> output "15" Query3: 2 PAT000001 -> employeeTickets["PAT000001"]: [1,2] -> wins: none -> output empty line. Query4: 3 -10 -> ticket -10 not found -> "ERROR" Query5: 1 9999 -> lower_bound(9999) -> end -> "ERROR" Query6: 1 -10 -> lower_bound(-10) -> the first >=-10: The set: [-2000, -5, ...] lower_bound(-10): the first element >= -10 -> -5 -> output "PAT000003", and mark -5 as won. Query7: 3 2 -> ticket 2 exists -> employee PAT000001 -> output "PAT000001", and mark 2 as won. Query8: 1 0 -> lower_bound(0): first >=0 -> 1 -> output "PAT000001", and mark 1 as won. Query9: 3 1 -> exists -> output "PAT000001", mark 1 (again). Query10: 2 PAT000001 -> tickets [1,2]: both won -> output "1 2" Query11: 3 -2000 -> exists -> output "PAT102030", mark -2000. Output: PAT000008 15 [empty line] ERROR ERROR PAT000003 PAT000001 PAT000001 PAT000001 1 2 PAT102030 So we output 11 lines. But the problem sample output is: PAT000008 15 ERROR ERROR PAT000003 PAT000001 PAT000001 PAT000001 1 2 PAT102030 How many lines? 10? Actually, the first two lines: PAT000008 15 Then the third line is empty, then the rest: 8 lines? total 11. The problem sample output is written as 10 lines? But they show 10 lines of text? Actually, they show: Line1: PAT000008 Line2: 15 Line3: (blank) -> so they skip a line? Then Line4: ERROR ... So the output has 11 lines. Therefore, we output 11 lines. We code accordingly. However, note: the problem says "output the employee ID holding the winning ticket" for type1 and type3, and for type2 we output the list of numbers (if any) or an empty line. We use: ios::sync_with_stdio(false); cin.tie(0); for speed. We use long long for the ticket numbers. Let me run with the sample to be sure. But note: the problem says "code without comments". So we remove comments. Final code: #include <iostream> #include <vector> #include <set> #include <map> #include <string> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); int N; cin >> N; set<long long> ticketSet; map<long long, string> ticketToOwner; set<long long> globalWinningTickets; map<string, vector<long long>> employeeTickets; for (int i = 0; i < N; i++) { string emp; long long x; cin >> emp >> x; ticketSet.insert(x); ticketToOwner[x] = emp; employeeTickets[emp].push_back(x); } int Q; cin >> Q; while (Q--) { int type; cin >> type; if (type == 1) { long long x; cin >> x; auto it = ticketSet.lower_bound(x); if (it == ticketSet.end()) { cout << "ERROR\n"; } else { cout << ticketToOwner[*it] << '\n'; globalWinningTickets.insert(*it); } } else if (type == 2) { string y; cin >> y; if (employeeTickets.find(y) == employeeTickets.end()) { cout << "ERROR\n"; } else { const vector<long long>& tickets = employeeTickets[y]; vector<long long> wins; for (long long t : tickets) { if (globalWinningTickets.find(t) != globalWinningTickets.end()) { wins.push_back(t); } } for (int i = 0; i < wins.size(); i++) { if (i > 0) cout << ' '; cout << wins[i]; } cout << '\n'; } } else if (type == 3) { long long x; cin >> x; if (ticketSet.find(x) == ticketSet.end()) { cout << "ERROR\n"; } else { cout << ticketToOwner[x] << '\n'; globalWinningTickets.insert(x); } } } return 0; } This should meet the constraints. Let me test with the sample input. But note: the sample input has 10 tickets and 11 queries. We'll run the sample input: Input: 10 PAT000001 1 PAT000003 5 PAT000002 4 PAT000010 20 PAT000001 2 PAT000008 7 PAT000010 18 PAT000003 -5 PAT102030 -2000 PAT000008 15 11 1 10 2 PAT000008 2 PAT000001 3 -10 1 9999 1 -10 3 2 1 0 3 1 2 PAT000001 3 -2000 Expected output: PAT000008 15 (empty line) ERROR ERROR PAT000003 PAT000001 PAT000001 PAT000001 1 2 PAT102030 We output: Line1: PAT000008 Line2: 15 Line3: (empty) -> so we output a newline? so it's a blank line. Line4: ERROR Line5: ERROR Line6: PAT000003 Line7: PAT000001 Line8: PAT000001 Line9: PAT000001 Line10: 1 2 Line11: PAT102030 So it matches. We note: the problem says "For actions of type 1 and 3, output the employee ID holding the winning ticket." and we do. We note: the problem says "For actions of type 2, if the employee ID y does not exist, output ERROR. Otherwise, output all winning ticket numbers ... in the same order of input. If no ticket wins, output an empty line instead." -> we do. We are using sets and maps which are efficient. We hope it meets the constraints: 10^5 operations, each set/map operation is O(log n) so total O((N+Q) * log N) which is about (10^5+10^5)*log2(10^5) = 200000 * 17 = 3.4e6 operations, which is acceptable. And the memory: about 10^5 nodes in sets and maps, which is acceptable. We output the code without comments. However, note: the problem says "code without comments", so we remove all comments. Final code: #include <iostream> #include <vector> #include <set> #include <map> #include <string> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); int N; cin >> N; set<long long> ticketSet; map<long long, string> ticketToOwner; set<long long> globalWinningTickets; map<string, vector<long long>> employeeTickets; for (int i = 0; i < N; i++) { string emp; long long x; cin >> emp >> x; ticketSet.insert(x); ticketToOwner[x] = emp; employeeTickets[emp].push_back(x); } int Q; cin >> Q; while (Q--) { int type; cin >> type; if (type == 1) { long long x; cin >> x; auto it = ticketSet.lower_bound(x); if (it == ticketSet.end()) { cout << "ERROR\n"; } else { cout << ticketToOwner[*it] << '\n'; globalWinningTickets.insert(*it); } } else if (type == 2) { string y; cin >> y; if (employeeTickets.find(y) == employeeTickets.end()) { cout << "ERROR\n"; } else { const vector<long long>& tickets = employeeTickets[y]; vector<long long> wins; for (long long t : tickets) { if (globalWinningTickets.find(t) != globalWinningTickets.end()) { wins.push_back(t); } } for (int i = 0; i < wins.size(); i++) { if (i > 0) cout << ' '; cout << wins[i]; } cout << '\n'; } } else if (type == 3) { long long x; cin >> x; if (ticketSet.find(x) == ticketSet.end()) { cout << "ERROR\n"; } else { cout << ticketToOwner[x] << '\n'; globalWinningTickets.insert(x); } } } return 0; } We run it with the sample and hope it passes. Note: the problem says "memory less than 64MB" and "time less than 200ms". We hope so. Let me test with a worst-case: 10^5 tickets and 10^5 queries. Worst-case: all tickets are distinct and belong to distinct employees? Then employeeTickets has 10^5 entries, each vector has size 1. Then for type2: we have at most 100 type2 queries, each takes O(1) to traverse the vector. The type1 and type3: each O(log n). So total time O((10^5)*log(10^5)) which is about 1.7e6 operations, which is acceptable. Memory: about 10^5 * (size of a node in set: 3 pointers + value: 8 bytes for long long -> 24+8=32 bytes per node? so 3.2e6 bytes for the set, and the map: 10^5 * (8+ say 9 for the string) -> but the string is stored per ticket? and we have 10^5 tickets -> 10^5 * (8+9) = 1.7e6 bytes? Then the employeeTickets: 10^5 * (size of string as key: 9 bytes? and vector: 24 bytes per vector + 8 bytes for the long long) -> 10^5 * (9 + 24 + 8) = 4.1e6 bytes. Total about 10 MB? So 64 MB is safe. We are ready. However, note: the problem says the employee ID is a string of the form "PATxxxxxx", which is 9 characters. But in C++ the string also stores the length and may have a small overhead. But 10^5 strings: 10^5 * (9+some overhead) is acceptable. We output the code as above. But note: the problem says "code without comments", so we have removed comments. We hope it passes. If there is an issue: the problem says "the same ticket can win multiple times", but we are only storing it once in the globalWinningTickets set. That is acceptable because we only need to know that it has won at least once. And for type2, we output the ticket number once per distinct winning ticket (and in the order of input) -> that matches. We are done. Let me check the sample again: for the employee PAT000001, we output "1 2" at the end. But note: the ticket 1 was won twice? But we output it only once. The problem says "output all winning ticket numbers" meaning each distinct winning ticket? Yes. So the code is correct. We output the code in markdown.</think>### C++ Solution for Lucky Draw Problem The solution efficiently handles the three types of actions (queries) by utilizing sets and maps for quick lookups and maintaining the order of tickets for each employee. The approach ensures optimal performance within the constraints. #### Approach 1. **Data Structures**: - **`ticketSet`**: A sorted set of all ticket numbers for efficient range queries (lower_bound). - **`ticketToOwner`**: A map linking each ticket number to its owner's employee ID. - **`globalWinningTickets`**: A set to track tickets that have won at least once. - **`employeeTickets`**: A map associating each employee ID with their list of tickets (in input order). 2. **Processing Queries**: - **Type 1 (1 x)**: Find the smallest ticket number ≥ x using `lower_bound`. Output the owner or "ERROR" if not found. Mark the ticket as won. - **Type 2 (2 y)**: Output all winning tickets for employee y in input order. If the employee doesn't exist, output "ERROR". If no winning tickets, output an empty line. - **Type 3 (3 x)**: Output the owner of ticket x or "ERROR" if not found. Mark the ticket as won. #### Solution Code ```cpp #include <iostream> #include <vector> #include <set> #include <map> #include <string> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); int N; cin >> N; set<long long> ticketSet; map<long long, string> ticketToOwner; set<long long> globalWinningTickets; map<string, vector<long long>> employeeTickets; for (int i = 0; i < N; i++) { string emp; long long x; cin >> emp >> x; ticketSet.insert(x); ticketToOwner[x] = emp; employeeTickets[emp].push_back(x); } int Q; cin >> Q; while (Q--) { int type; cin >> type; if (type == 1) { long long x; cin >> x; auto it = ticketSet.lower_bound(x); if (it == ticketSet.end()) { cout << "ERROR\n"; } else { cout << ticketToOwner[*it] << '\n'; globalWinningTickets.insert(*it); } } else if (type == 2) { string y; cin >> y; if (employeeTickets.find(y) == employeeTickets.end()) { cout << "ERROR\n"; } else { const vector<long long>& tickets = employeeTickets[y]; vector<long long> wins; for (long long t : tickets) { if (globalWinningTickets.find(t) != globalWinningTickets.end()) { wins.push_back(t); } } for (int i = 0; i < wins.size(); i++) { if (i > 0) cout << ' '; cout << wins[i]; } cout << '\n'; } } else if (type == 3) { long long x; cin >> x; if (ticketSet.find(x) == ticketSet.end()) { cout << "ERROR\n"; } else { cout << ticketToOwner[x] << '\n'; globalWinningTickets.insert(x); } } } return 0; } ``` #### Explanation - **Initialization**: The code reads all tickets, storing each ticket in `ticketSet`, mapping each ticket to its owner in `ticketToOwner`, and grouping tickets by employee in `employeeTickets`. - **Query Processing**: - **Type 1 (1 x)**: Uses `lower_bound` to find the smallest ticket ≥ x. If found, outputs the owner and marks the ticket as won. - **Type 2 (2 y)**: Checks if the employee exists. If so, collects all winning tickets in input order and outputs them space-separated (or an empty line if none). - **Type 3 (3 x)**: Checks if the ticket exists. If so, outputs the owner and marks the ticket as won. - **Efficiency**: The use of sets and maps ensures O(log N) per query, making the solution efficient for large inputs (N, Q ≤ 10^5). This approach efficiently handles all query types while maintaining optimal performance and memory usage. --- **
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值