题意:
远程电话的收费是按照每分钟来计费的,现在告诉你一天24小时中每分钟的收费标准,以及n条通话记录,试求出每个人该月的消费账单。
只有开始记录没有结束记录的通话不计费,反之亦然。保证所有消费记录在同一个月,且至少含有一条满足计费的账单记录。
输出是需要输出用户姓名,月份,每一条记录的开始结束时间于计费,总计费。按照用户名升序输出账单。
思路:
常规的一个时间差计算题,但是该题细节较多,也有许多坑点。先按照用户名升序,再按照时间升序来排序。再依次处理每次完整的通话。
刚开始是考虑前缀和直接获取时间段对应的计费,但是已知过不了1、2测试点。
坑点:没有完整消费记录的用户不用输出账单,虽然我跳过了这个坑,但是为注意自己的”Total amount: $“是在判断以外输出的,这会导致无消费的账单同样有这句输出。
后来换了一个直接计算的思路,最后发现是输出的锅,哎~.
前缀和的代码:
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 6e5+10;
int c[25];
int n, tt;
int s[N], pre[N];
string na, tmp, line, month;
map<string, int> vis;
struct node{
string name;
string time;
int tag;
int tm;
}r[N];
int get_int(char x){
return x-'0';
}
int trans(string s){
int res = get_int(s[0])*10+get_int(s[1]);
res *= 24;
res += get_int(s[3])*10+get_int(s[4]);
res *= 60;
res += get_int(s[6])*10+get_int(s[7]);
return res;
}
bool cmp(node a, node b){
if(a.name==b.name) return a.tm<b.tm;
return a.name<b.name;
}
signed main()
{
for(int i = 0; i < 24; i ++){
cin >> c[i];
for(int j = 1; j <= 60; j ++){
s[++tt] = c[i];
pre[tt] = pre[tt-1]+c[i];
}
}
cin >> n;
for(int i = 1; i <= n; i ++){
cin >> na >> tmp >> line;
r[i].name = na;
r[i].time = tmp.substr(3, 8);
r[i].tm = trans(r[i].time);
if(line[1]=='n') r[i].tag = 1;
else r[i].tag = 2;
if(month.size()==0) month = tmp.substr(0, 2);
}
sort(r+1, r+n+1, cmp);
for(int i = 1; i <= n; i ++){
if(!vis[r[i].name]){
na = r[i].name;
vis[na] ++;
double tot = 0;
bool flag = 0;
for(int j = i; j < n; j ++){
if(r[j].tag==1 && r[j+1].tag==2 && r[j+1].name==r[j].name){
if(vis[r[j].name]==1){
cout << na << " " << month << endl;
vis[na] ++;
}
double cost = 0;
int rep = get_int(r[j].time[0])*10+get_int(r[j].time[1]);
rep *= 24*60;
if(r[j].time.substr(0, 2) == r[j+1].time.substr(0,2)){
cost = pre[r[j+1].tm-rep]-pre[r[j].tm-rep];
}
else{
cost += pre[24*60]-pre[r[j].tm-rep];
int days = stoi(r[j+1].time.substr(0,2))-stoi(r[j].time.substr(0, 2))-1;
cost += days*pre[24*60];
int rep1 = get_int(r[j+1].time[0])*10+get_int(r[j+1].time[1]);
rep1 *= 24*60;
cost += pre[r[j+1].tm-rep1];
}
tot += cost*0.01;
cout << r[j].time << " " << r[j+1].time << " " << r[j+1].tm-r[j].tm << " $";
cout << fixed << setprecision(2) << cost*0.01 << endl;
flag = 1;
}
if(r[j+1].name!=na){
i = j-1;
break;
}
}
if(flag) cout << "Total amount: $" << tot << endl;
}
}
return 0;
}
直接计算的代码:
#include<bits/stdc++.h>
//#define int long long
#define endl '\n'
using namespace std;
const int N = 6e5+10;
int c[25], sum;
int n, tt;
int s[N], pre[N];
string na, tmp, line, month;
map<string, int> vis;
struct node{
string name;
string time;
int tag;
int tm;
}r[N];
int get_int(char x){
return x-'0';
}
int trans(string s){
int res = get_int(s[0])*10+get_int(s[1]);
res *= 24;
res += get_int(s[3])*10+get_int(s[4]);
res *= 60;
res += get_int(s[6])*10+get_int(s[7]);
return res;
}
bool cmp(node a, node b){
if(a.name==b.name) return a.tm<b.tm;
return a.name<b.name;
}
int get_difference(string ed, string bg){
int res = 0;
int day0 = stoi(bg.substr(0,2)), day1 = stoi(ed.substr(0,2));
int hour0 = stoi(bg.substr(3,2)), hour1 = stoi(ed.substr(3,2));
int minute0 = stoi(bg.substr(6,2)), minute1 = stoi(ed.substr(6,2));
if(day0==day1){ // 同一天
// cout << "同一天" << endl;
if(hour0==hour1){ // 同一小时
res += (minute1-minute0)*c[hour0];
// cout << "同一小时 -> res: " << res << endl;
}else{ // 不同小时
// cout << "不同小时:" << endl;
res += (60-minute0)*c[hour0];
// cout << "加上开始剩余分钟的 -> res: " << (60-minute0)*c[hour0] << endl;
for(int i = hour0+1; i < hour1; i ++) res += 60*c[i];
// cout << "加上中间小时的 -> res: " << res << endl;
res += minute1*c[hour1];
// cout << "加上结束剩余分钟的 -> res: " << res << endl;
}
}else{
// cout << "不同天" << endl;
res += (60-minute0)*c[hour0];
// cout << "加上开始剩余分钟的 -> res: " << res << endl;
for(int i = hour0+1; i < 24; i ++){ // 开始当天的消费
res += 60*c[i];
}
// cout << "加上开始剩余小时的 -> res: " << res << endl;
res += (day1-day0-1)*sum; // 中间几天的消费
// cout << "加上中间" << (hour1-hour0-1) << "天的 -> res: " << res << endl;
for(int i = 0; i < hour1; i ++){
res += 60*c[i];
}
// cout << "加上结束剩余小时的 -> res: " << res << endl;
res += minute1*c[hour1]; // 结束当天的消费
// cout << "加上结束剩余分钟的 -> res: " << res << endl;
}
return res;
}
signed main()
{
for(int i = 0; i < 24; i ++){
cin >> c[i];
sum += c[i]*60;
}
cin >> n;
for(int i = 1; i <= n; i ++){
cin >> na >> tmp >> line;
r[i].name = na;
r[i].time = tmp.substr(3, 8);
r[i].tm = trans(r[i].time);
if(line[1]=='n') r[i].tag = 1;
else r[i].tag = 2;
if(month.size()==0) month = tmp.substr(0, 2);
}
sort(r+1, r+n+1, cmp);
for(int i = 1; i <= n; i ++){
if(!vis[r[i].name]){
na = r[i].name;
vis[na] ++;
double tot = 0;
bool flag = 0;
for(int j = i; j < n; j ++){
if(r[j].tag==1 && r[j+1].tag==2 && r[j+1].name==r[j].name){
if(vis[r[j].name]==1){
cout << na << " " << month << endl;
vis[na] ++;
}
double cost = get_difference(r[j+1].time, r[j].time);
tot += cost*0.01;
cout << r[j].time << " " << r[j+1].time << " " << r[j+1].tm-r[j].tm << " $";
cout << fixed << setprecision(2) << cost*0.01 << endl;
flag = 1;
}
if(r[j+1].name!=na){
i = j-1;
break;
}
}
if(flag) cout << "Total amount: $" << tot << endl;
}
}
return 0;
}