【PAT】1016. Phone Bills (25)【priority_queue和map的使用】

题目描述

A long-distance telephone company charges its customers by the following rules:

Making a long-distance call costs a certain amount per minute, depending on the time of day when the call is made. When a customer starts connecting a long-distance call, the time will be recorded, and so will be the time when the customer hangs up the phone. Every calendar month, a bill is sent to the customer for each minute called (at a rate determined by the time of day). Your job is to prepare the bills for each month, given a set of phone call records.

翻译:一个长途通话公司根据以下规则对它的客户记账:
打一个长途通话每分钟花费某一确定数量的美分,由打电话的时间所决定。当一个用户开始长途通话时,时间将会被记录,同样结束长途通话的时间也会被记录。每个月,一份包括每一分钟的通话费(费用由当天时间决定)账单将会寄给消费者。你的任务是为每个月计算账单,一份通话记录已给出。

INPUT FORMAT

Each input file contains one test case. Each case has two parts: the rate structure, and the phone call records.

The rate structure consists of a line with 24 non-negative integers denoting the toll (cents/minute) from 00:00 - 01:00, the toll from 01:00 - 02:00, and so on for each hour in the day.

The next line contains a positive number N (<= 1000), followed by N lines of records. Each phone call record consists of the name of the customer (string of up to 20 characters without space), the time and date (mm:dd:hh:mm), and the word “on-line” or “off-line”.

For each test case, all dates will be within a single month. Each “on-line” record is paired with the chronologically next record for the same customer provided it is an “off-line” record. Any “on-line” records that are not paired with an “off-line” record are ignored, as are “off-line” records not paired with an “on-line” record. It is guaranteed that at least one call is well paired in the input. You may assume that no two records for the same customer have the same time. Times are recorded using a 24-hour clock.
翻译:每个测试文件包含一组测试数据。每组测试数据包括2部分:费用安排和通话记录。
费用安排由一行24个非负整数组成,分别为00:00 - 01:00的长途电话费,01:00 - 02:00的长途通话费,以此类推。
接下来一行包括一个正整数N (<= 1000),接着N行为通话记录。每个通话记录由用户名(20个字符不包含空格)、月份和日期 (mm:dd:hh:mm),和单词 “on-line” or “off-line”。
对于每组测试数据,所有的日期都在同一月内。每个“on-line”记录与按时间先后顺序排列的同一用户提供的“off-line”记录相配对。任何“on-line”记录如果未与“off-line”记录匹配则被忽略,”off-line”记录也是。数据保证输入中至少有一组通话记录可以匹配。你需要假设同一个用户不能在同一时间同时打两个电话。时间为24小时制。

OUTPUT FORMAT

For each test case, you must print a phone bill for each customer.

Bills must be printed in alphabetical order of customers’ names. For each customer, first print in a line the name of the customer and the month of the bill in the format shown by the sample. Then for each time period of a call, print in one line the beginning and ending time and date (dd:hh:mm), the lasting time (in minute) and the charge of the call. The calls must be listed in chronological order. Finally, print the total charge for the month in the format shown by the sample.

翻译:对于每组测试数据,你需要输出一份通话账单给每个客户。
账单必须按照客户姓名的字母序输出。对于每个客户,首先输出一行包括他的姓名和账单月份像样例中那样。接着对于每次通话记录,以 (dd:hh:mm)格式输出开始时间、结束时间,持续时间(分钟)和通话的花费。通话记录必须按照时间先后顺序排序。最后,像样例中展示的格式那样输出该月的总费用。


Sample Input:

10 10 10 10 10 10 20 20 20 15 15 15 15 15 15 15 20 30 20 15 15 10 10 10
10
CYLL 01:01:06:01 on-line
CYLL 01:28:16:05 off-line
CYJJ 01:01:07:00 off-line
CYLL 01:01:08:03 off-line
CYJJ 01:01:05:59 on-line
aaa 01:01:01:03 on-line
aaa 01:02:00:01 on-line
CYLL 01:28:15:41 on-line
aaa 01:05:02:24 on-line
aaa 01:04:23:59 off-line


Sample Output:

CYJJ 01
01:05:59 01:07:00 61 $12.10
Total amount: $12.10
CYLL 01
01:06:01 01:08:03 122 $24.40
28:15:41 28:16:05 24 $3.85
Total amount: $28.25
aaa 01
02:00:01 04:23:59 4318 $638.80
Total amount: $638.80


解题思路

这道题理解题意就挺麻烦的,是道大模拟题。首先需要将用户保存到一个map< string, int >,用于维护用户号。然后将string压到一个优先队列中,对string按字母序排序,再创建一个优先队列数组,用于保存通话记录。当然,这些数据结构都可以进行合并,根据个人喜好即可。注意:如果一个用户没有有效通话记录,则不输出!!很坑,怪我英文太差。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
#define INF 99999999
using namespace std;
struct Call{
    int d,h,m,state;
    Call(int day,int hour,int minute,int st):d(day),h(hour),m(minute),state(st){}
    bool operator <(const Call &a)const{
        return d==a.d?(h==a.h?m>a.m:h>a.h):d>a.d;   
    }
};
map<string,int> mp;
priority_queue<Call> q[1001];
priority_queue<string,vector<string>,greater<string> > qS;
int N,ccount=1,Mon[1010];//ccount用于记录客户号 
double cost[24];
int Count(Call a,Call b){
    int ad=a.d,ah=a.h,am=a.m;
    int bd=b.d,bh=b.h,bm=b.m;
    return ((bd-ad)*24+(bh-ah))*60+bm-am;
}
double Bill(Call a,Call b){
    int ad=a.d,ah=a.h,am=a.m;
    int bd=b.d,bh=b.h,bm=b.m;
    ah=ah%24;bh=bh%34;
    double sum=0.0;
    while(ad<bd||ah<bh){
        sum+=cost[ah]*(60-am);am=0;ah++;
        if(ah==24)ah=0,ad++;
    }
    sum+=(bm-am)*cost[ah];
    return sum/100;
} 
int main(){
    for(int i=0;i<24;i++)
    scanf("%lf",&cost[i]);
    scanf("%d",&N);
    string s,state;
    state.resize(10);
    int mon,day,hour,min;
    for(int i=0;i<N;i++){
        cin>>s;
        scanf("%d:%d:%d:%d %s",&mon,&day,&hour,&min,state.c_str());
        if(!mp[s])mp[s]=ccount,qS.push(s),Mon[ccount++]=mon;
        if(state[1]=='f')q[mp[s]].push(Call(day,hour,min,0));
        else             q[mp[s]].push(Call(day,hour,min,1));
    }
    while(!qS.empty()){
        string tempS=qS.top();qS.pop();
        Call pre(0,0,0,-1);
        int Pre=0,flag=0;
        double Sum=0;
        while(!q[mp[tempS]].empty()){
            Call tempC=q[mp[tempS]].top();q[mp[tempS]].pop();
            if(tempC.state==1)pre=tempC,Pre=1;
            if(tempC.state==0&&Pre){
                double sum=Bill(pre,tempC);
                if(!flag){
                    cout<<tempS;
                    printf(" %02d\n",Mon[mp[tempS]]);
                    flag=1; 
                }
                Sum+=sum;
                printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2lf\n",pre.d,pre.h,pre.m,tempC.d,tempC.h,tempC.m,Count(pre,tempC),sum);
                Pre=0;
            }
        }
        if(flag)printf("Total amount: $%.2lf\n",Sum);
    }
    return 0;
}


优化这个sql SELECT count( 1 ) FROM ( SELECT B.ID, B.PURCHASE_REQUEST_ID, B.MATERIAL_ID, B.MATERIAL_CODE, B.MATERIAL_NAME, B.STANDARD, B.MODEL_ID, B.BILL_ROW_ID, B.BILL_NO, BILL_NAME, B.MODEL_CODE, B.MODEL_NAME, B.PARENT_MODEL_ID, B.PARENT_MODEL_CODE, B.PARENT_MODEL_NAME, B.UNIT_CODE, B.UNIT_NAME, B.PURCHASE_TYPE_CODE, CAST( NVL( B.APPLY_NUM, 0 ) AS NUMBER ( 24, 10 ) ) AS APPLY_NUM, CAST( NVL( B.DEAL_NUM, 0 ) AS NUMBER ( 24, 10 ) ) AS DEAL_NUM, CAST( NVL( B.RETURN_NUM, 0 ) AS NUMBER ( 24, 10 ) ) AS RETURN_NUM, B.DEAL_USER_ID, B.DEAL_USER_NAME, CAST( NVL( B.PRICE, 0 ) AS NUMBER ( 24, 10 ) ) AS PRICE, CAST( NVL( B.AMOUNT, 0 ) AS NUMBER ( 24, 10 ) ) AMOUNT, B.IMPLEMENT_CODE, B.IMPLEMENT_NAME, B.IMPLEMENT_INVEST_AMOUNT, B.PURCHASE_MANAGER_ID, B.PURCHASE_MANAGER_NAME, B.PROVIDER_ID, B.PROVIDER_NAME, B.REMARK, B.DELIVER_AREA, B.DELIVER_ADDRESS, B.RECEIVE_PEOPLE, B.RECEIVE_PEOPLE_PHONE, B.ITEM_STATUS, B.COST_CENTER, B.COST_BUDGET_CODE, B.COST_IMPLEMENT_NAME, B.FRAME_CONT_ID, B.FRAME_CONT_CODE, B.FRAME_CONT_NAME, B.DETAIL_CONFIG, B.PURCHASE_CATEGORY_CODE, B.INVOICE_TITLE_CODE, B.INVOICE_SEND_ADDRRSS, B.MATERIAL_REQUEST_ITEM_ID, B.YEAR, B.DELETE_FLAG, B.PROVINCE_CODE, B.REASON, B.PARENT_ITEM_ID, B.FRAME_CONT_ITEM_ID, B.SUB_MATERIAL_REQUEST_ID, B.SUB_MATERIAL_REQUEST_CODE, B.MATERIAL_URL, B.RECOMMEND_PROVIDER_NAMES, C.PURCHASE_REQUEST_CODE, C.PURCHASE_REQUEST_NAME, C.APPLY_TYPE_CODE, C.CREATOR_NAME, C.APPLY_TELEPHONE, C.COMPANY_NAME, C.DEPT_NAME, B.CREATE_TIME, TO_CHAR( B.CREATE_TIME, 'YYYY-MM-DD' ) CREATE_TIME_STR, C.ARRIVE_TIME, C.IS_TO_END, C.MONEY_WAY_CODE, C.OWN, C.APPLY_CATEGORY_CODE, C.manu_Type, C.BILL_ID, MMD.MATERIAL_TYPE_CODE, B.BRANCH_COMPANY_DEAL_USER_ID, B.BRANCH_COMPANY_DEAL_USER_NAME, ( SELECT ORG_NAME FROM ORGANIZATIONS WHERE DELETE_FLAG = '0' AND ORG_CODE = ( SELECT PARENT_COMPANY_NO FROM ORGANIZATIONS WHERE ID = B.MATERIAL_DEPT_ID )) AS MATERIAL_COMPANY_NAME, B.ORIGINAL, B.PROVIDER_PRODUCT_MODEL, B.PROVIDER_PRODUCT_NAME, B.PRODUCT_DESC, B.Back_Flag, CASE WHEN MMD.material_type_code = 'WZ' THEN '1' WHEN MMD.material_type_code = 'FW' THEN '2' ELSE '3' END apply_category_code_item, NVL( C.IS_CARDSYSTEM_REQUEST, '0' ) IS_CARDSYSTEM_REQUEST, B.APPLY_GROUP_AUTHORITES, B.SCIENTIFIC_RESEARCH_ID, B.SCIENTIFIC_RESEARCH_CODE, B.SCIENTIFIC_RESEARCH_NAME, B.PREQUALFY_CODE, nvl( C.IS_QUICK, '0' ) AS IS_QUICK, C.PURCHASE_WAY_CODE, C.PURCHASE_TYPE_CODE PURCHASE_TYPE_CODE_P, C.ORIGINAL_TYPE, C.PURCHASE_REQUEST_BILLS_TYPE, B.IS_FRAME_CONT_MONAD FROM PURCHASE_REQUEST_ITEM B LEFT JOIN PURCHASE_REQUEST C ON B.PURCHASE_REQUEST_ID = C.ID LEFT JOIN MATERIAL_DATA MMD ON MMD.ID = B.MATERIAL_ID AND MMD.DELETE_FLAG = '0' WHERE B.delete_flag = '0' AND B.Item_Status IN ( 1 ) AND NOT EXISTS ( SELECT * FROM purchase_request_item_log pril WHERE B.id = pril.purchase_request_item_id AND pril.lock_status = '1' AND pril.delete_flag = '0' ) AND ( ( c.apply_type_code NOT IN ( '20', '41', '3' ) AND nvl( B.Apply_Num, 0 ) > nvl( B.Deal_Num, 0 )) OR c.apply_type_code IN ( '20', '41', '3' ) ) AND B.Deal_User_Id =: 1 AND C.MONEY_WAY_CODE =: 2 AND C.APPLY_TYPE_CODE =: 3 AND C.PAY_OUT_TYPE_CODE =: 4 AND C.APPLY_CATEGORY_CODE =: 5 AND NVL( C.IS_CARDSYSTEM_REQUEST, '0' ) = : 6 AND NOT EXISTS ( SELECT * FROM purchase_request_item p left join material_province mp ON p.material_id = mp.material_id WHERE p.delete_flag = 0 AND mp.delete_flag = 0 AND mp.material_status = 03 AND mp.org_code = p.province_code AND p.id = B.id ) ORDER BY C.ID, B.ID ASC)
06-08
首先,可以将子查询中的所有列名改为别名,这样可以避免重名提高代码可读性。另外,可以尝试使用 EXISTS 子查询来替换 NOT EXISTS 子查询,因为 EXISTS 子查询的性能通常更好。最后,可以考虑对 WHERE 子句中的多个条件进行逻辑上的分组,以避免出现过于复杂的条件表达式。下面是优化后的 SQL: SELECT COUNT(1) FROM ( SELECT b.ID, b.PURCHASE_REQUEST_ID, b.MATERIAL_ID, b.MATERIAL_CODE, b.MATERIAL_NAME, b.STANDARD, b.MODEL_ID, b.BILL_ROW_ID, b.BILL_NO, b.BILL_NAME, b.MODEL_CODE, b.MODEL_NAME, b.PARENT_MODEL_ID, b.PARENT_MODEL_CODE, b.PARENT_MODEL_NAME, b.UNIT_CODE, b.UNIT_NAME, b.PURCHASE_TYPE_CODE, CAST(NVL(b.APPLY_NUM, 0) AS NUMBER(24, 10)) AS APPLY_NUM, CAST(NVL(b.DEAL_NUM, 0) AS NUMBER(24, 10)) AS DEAL_NUM, CAST(NVL(b.RETURN_NUM, 0) AS NUMBER(24, 10)) AS RETURN_NUM, b.DEAL_USER_ID, b.DEAL_USER_NAME, CAST(NVL(b.PRICE, 0) AS NUMBER(24, 10)) AS PRICE, CAST(NVL(b.AMOUNT, 0) AS NUMBER(24, 10)) AMOUNT, b.IMPLEMENT_CODE, b.IMPLEMENT_NAME, b.IMPLEMENT_INVEST_AMOUNT, b.PURCHASE_MANAGER_ID, b.PURCHASE_MANAGER_NAME, b.PROVIDER_ID, b.PROVIDER_NAME, b.REMARK, b.DELIVER_AREA, b.DELIVER_ADDRESS, b.RECEIVE_PEOPLE, b.RECEIVE_PEOPLE_PHONE, b.ITEM_STATUS, b.COST_CENTER, b.COST_BUDGET_CODE, b.COST_IMPLEMENT_NAME, b.FRAME_CONT_ID, b.FRAME_CONT_CODE, b.FRAME_CONT_NAME, b.DETAIL_CONFIG, b.PURCHASE_CATEGORY_CODE, b.INVOICE_TITLE_CODE, b.INVOICE_SEND_ADDRRSS, b.MATERIAL_REQUEST_ITEM_ID, b.YEAR, b.DELETE_FLAG, b.PROVINCE_CODE, b.REASON, b.PARENT_ITEM_ID, b.FRAME_CONT_ITEM_ID, b.SUB_MATERIAL_REQUEST_ID, b.SUB_MATERIAL_REQUEST_CODE, b.MATERIAL_URL, b.RECOMMEND_PROVIDER_NAMES, c.PURCHASE_REQUEST_CODE, c.PURCHASE_REQUEST_NAME, c.APPLY_TYPE_CODE, c.CREATOR_NAME, c.APPLY_TELEPHONE, c.COMPANY_NAME, c.DEPT_NAME, b.CREATE_TIME, TO_CHAR(b.CREATE_TIME, 'YYYY-MM-DD') CREATE_TIME_STR, c.ARRIVE_TIME, c.IS_TO_END, c.MONEY_WAY_CODE, c.OWN, c.APPLY_CATEGORY_CODE, c.manu_Type, c.BILL_ID, MMD.MATERIAL_TYPE_CODE, b.BRANCH_COMPANY_DEAL_USER_ID, b.BRANCH_COMPANY_DEAL_USER_NAME, (SELECT ORG_NAME FROM ORGANIZATIONS WHERE DELETE_FLAG = '0' AND ORG_CODE = (SELECT PARENT_COMPANY_NO FROM ORGANIZATIONS WHERE ID = b.MATERIAL_DEPT_ID)) AS MATERIAL_COMPANY_NAME, b.ORIGINAL, b.PROVIDER_PRODUCT_MODEL, b.PROVIDER_PRODUCT_NAME, b.PRODUCT_DESC, b.Back_Flag, CASE WHEN MMD.material_type_code = 'WZ' THEN '1' WHEN MMD.material_type_code = 'FW' THEN '2' ELSE '3' END apply_category_code_item, NVL(c.IS_CARDSYSTEM_REQUEST, '0') IS_CARDSYSTEM_REQUEST, b.APPLY_GROUP_AUTHORITES, b.SCIENTIFIC_RESEARCH_ID, b.SCIENTIFIC_RESEARCH_CODE, b.SCIENTIFIC_RESEARCH_NAME, b.PREQUALFY_CODE, NVL(c.IS_QUICK, '0') AS IS_QUICK, c.PURCHASE_WAY_CODE, c.PURCHASE_TYPE_CODE PURCHASE_TYPE_CODE_P, c.ORIGINAL_TYPE, c.PURCHASE_REQUEST_BILLS_TYPE, b.IS_FRAME_CONT_MONAD FROM PURCHASE_REQUEST_ITEM b LEFT JOIN PURCHASE_REQUEST c ON b.PURCHASE_REQUEST_ID = c.ID LEFT JOIN MATERIAL_DATA MMD ON MMD.ID = b.MATERIAL_ID AND MMD.DELETE_FLAG = '0' WHERE b.delete_flag = '0' AND b.Item_Status IN (1) AND b.Deal_User_Id = :1 AND C.MONEY_WAY_CODE = :2 AND C.APPLY_TYPE_CODE = :3 AND C.PAY_OUT_TYPE_CODE = :4 AND C.APPLY_CATEGORY_CODE = :5 AND NVL(C.IS_CARDSYSTEM_REQUEST, '0') = :6 AND EXISTS ( SELECT * FROM purchase_request_item_log pril WHERE B.id = pril.purchase_request_item_id AND pril.lock_status = '1' AND pril.delete_flag = '0' ) AND ( c.apply_type_code IN ('20', '41', '3') OR ( c.apply_type_code NOT IN ('20', '41', '3') AND NVL(b.Apply_Num, 0) > NVL(b.Deal_Num, 0) ) ) AND NOT EXISTS ( SELECT * FROM purchase_request_item p LEFT JOIN material_province mp ON p.material_id = mp.material_id WHERE p.delete_flag = 0 AND mp.delete_flag = 0 AND mp.material_status = 03 AND mp.org_code = p.province_code AND p.id = b.id ) ORDER BY c.ID, b.ID ASC )
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值