题目背景
2023年9月7日,一年一度的大学生数学建模竞赛开始了。众所周知,数学建模竞赛的C题是数据分析和处理题。然而今年的数据量非常大,最大的一个文件有878503条记录,巨大的数据量让很多选手都非常头疼。
题目描述
学过编程语言的你一定知道编程语言的运算速度非常快,想必如果你参加了今年的数学建模竞赛并且选择了C题的话一定能学以致用。下面是数据处理的一部分问题,一起来练练手吧。
现给定一家超市近三年的蔬菜销售记录,每一条销售记录有以下信息:
1.销售日期;
2.销售的蔬菜的编号;
3.该蔬菜的销售量。
现在需要你设计一个程序,可以满足以下要求:
输入蔬菜编号、起始日期和终止日期,则能输出该编号的蔬菜在这一段时间的总销售量。
输入格式
1.第一行一个正整数 n n n,表示有 n n n 条销售记录。( 1 ≤ n ≤ 1 0 6 1\leq n \leq 10^6 1≤n≤106)
2.接下来会有 n n n 行输入,每一行 2 2 2 个字符串 T 、 I D T、ID T、ID 和一个整数 W W W,分别表示销售时间、蔬菜编号和销售量。(数据保证 T T T 为 YYYY-MM-DD 的形式表示的时间、符合实际、按照时间顺序并且所有数据都在2020、2021、2022、2023四年内;ID为由15个数字字符组成的字符串,且保证不同的字符串至多251个;整数 W W W 满足 − 2 × 1 0 5 ≤ W ≤ 2 × 1 0 5 -2\times 10^5 \leq W \leq 2\times 10^5 −2×105≤W≤2×105)
3.接下来有一个正整数 q q q , 表示询问的次数。( 1 ≤ q ≤ 1 0 6 1\leq q \leq 10^6 1≤q≤106)
4.每次询问会输入 3 3 3 个参数 I D 、 T s 、 T d ID、T_s、 T_d ID、Ts、Td ,表示:询问在 [ T s , T d ] [T_s, T_d] [Ts,Td] 时间内,编号为 I D ID ID 的蔬菜的总销售量。( T s 、 T d T_s、T_d Ts、Td 保证在输入的 n n n 条销售记录中出现过)
输出格式
对于 q q q 次询问,每次询问,输出一行一个整数,表示在 [ T s , T d ] [T_s, T_d] [Ts,Td] 时间内,编号为 I D ID ID 的蔬菜的总销售量
测试样例
9
2020-07-01 102900005117056 396
2020-07-01 102900005115960 849
2020-07-01 102900005117056 409
2022-02-20 102900005115779 477
2022-02-20 102900005116899 389
2022-02-20 102900005115779 426
2023-06-30 106949711300259 1000
2023-06-30 106949711300259 1000
2023-06-30 102900011030059 1000
5
102900005117056 2020-07-01 2023-06-30
102900005115779 2022-02-20 2022-02-20
102900005115960 2022-02-20 2023-06-30
102900005116899 2022-02-20 2023-06-30
106949711300259 2020-07-01 2023-06-30
805
903
0
389
2000
思路
本题是想要询问一个特定编号的数字的区间出现次数和,对于每一个特定的编号的存储,我们可以使用一个哈希来进行存储,然后题目中的时间都是严格递增的,我们不需要进行额外的排序处理,可以直接线性判断或者二分查找都可以
核心代码
代码来自锕狗:
#include<bits/stdc++.h>
#define endl '\n'
using ld=long double;
using ll=long long;
using namespace std;
int n,q;
unordered_map<string,map<string,ll>> a;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cin>>n;
string x,y,z;
for(int i=1;i<=n;i++)
{
cin>>x>>y>>z;
a[y][x]+=stoi(z);
}
cin>>q;
while(q--)
{
cin>>x>>y>>z;
ll ans=0;
for(auto &t: a[x])
{
if(t.first<y)
continue;
if(t.first>z)
break;
ans+=t.second;
}
cout<<ans<<endl;
}
return 0;
}