题目链接:
Codeforces #669 Div2 E. Little Artem and Time Machine
题意:
定义一个元素重复集合multiset,然后在不同的时间对集合添加和删除元素操作,需要输出在不同的查询时间集合中元素出现的次数。
分析;
离线处理。首先将查询按照查询时间排序,然后检查所有在这个查询的输入之前的操作,
如果操作时间小于查询时间那么就执行,否则就存进一个优先队列中,等到时间够了再执行。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <cmath>
#include <ctime>
#include <cassert>
#include <queue>
#include <map>
#include <vector>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0)
using namespace std;
const int MAX_N=100010;
int n,total1,total2;
struct Query{
int id,step,data,ans;
}query[MAX_N];
struct Oper{
int id,step,data,flag;
//bool operator < (const Oper& rhs) const{
// return step > rhs.step;
//}
};
Oper oper[MAX_N];
bool cmp1(struct Query a,struct Query b)
{
return a.step<b.step;
}
bool cmp2(struct Query a,struct Query b)
{
return a.id < b.id;
}
struct cmp { //cmp比较函数,a<b返回1,否则返回0
bool operator () (const Oper& a,const Oper& b) const {
//因为优先队列是“大”的元素先出来,我们需要的是step小的先出来,只能定义a.step>b.step时a<b
return a.step > b.step;
}
};
int main()
{
freopen("Ein.txt","r",stdin);
while(~scanf("%d",&n)){
map<int,int> mp;
total1=total2=0;
for(int i=0;i<n;i++){
int t,a,b;
scanf("%d%d%d",&t,&a,&b);
if(t==1||t==2){
oper[total1].flag=(t==1?1:0); // 1.添加 0.删除
oper[total1].step=a;
oper[total1].data=b;
oper[total1].id=i;
total1++;
} else {
query[total2].step=a;
query[total2].data=b;
query[total2].id=i;
total2++;
}
}
sort(query,query+total2,cmp1); //按照查询的时间排序
priority_queue < Oper,vector<Oper>, cmp> que; //定义操作时间在前的先出的优先队列
for(int i=0,j=0;j<total2;j++){
while(i<total1 && oper[i].id < query[j].id){ //将所有在这次查询的输入之前的操作执行
int step=oper[i].step;
if(step>query[j].step){ //如果这次操作是在这次查询之后执行的
que.push(oper[i]); //先存进优先队列中
}else {
if(oper[i].flag==1) mp[oper[i].data]++; //添加元素
else mp[oper[i].data]--; //删除元素
}
i++;
}
while(1){ //查找之前操作中的所有操作时间在查询时间之前的操作
if(que.empty()) break;
Oper tmp=que.top();
//printf("tmp.step=%d \n",tmp.step);
if(tmp.step < query[j].step){
que.pop();
if(tmp.flag==1) mp[tmp.data]++;
else mp[tmp.data]--;
}else {
break;
}
}
query[j].ans=mp[query[j].data];
}
sort(query,query+total2,cmp2); //按照查询的输入顺序排序
for(int i=0;i<total2;i++){
printf("%d\n",query[i].ans);
}
}
return 0;
}