【题目描述】
CodeForces - 641ELittle Artem and Time Machine
【题目分析】
题目的意思大概是有三种操作
1.在时间t加入一个数字x
2.在时间t删除一个数字x
3.询问在时间t集合里面x的个数
虽然题目描述很简单,但是t和x的范围都是109,我一开始想到的是主席树,因为之前做过一道类似的题目HDU - 4348To the moon——主席树+区间修改,然后我就开始兴冲冲的开始离散化,然后正准备写主席树的维护的时候才发现因为这个时间是跳跃的,所以我们很不容易用到之前的数据,也不容易修改,所以卡住了。
在网上找其他大佬的博客发现用map以后就不用进行离散化了,而且代码量非常少,仔细一看发现他用的是树状数组,大概的思想就是对于每一个x都用一个树状数组维护时间区间,每次修改都在时间轴上进行修改,每次查询也只是针对这个数字在时间轴上进行查询。我觉得对每一个数字用一个线段树进行维护应该也可以做,就是得把每个数字的修改的时间进行离散化,然后再分别建树可能复杂度会有点高,但应该也是可做的吧,反正我是懒得那样做了,这个map+树状数组真的好爽啊,什么离散化什么的完全不需要啊。
【AC代码】
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;const int MAXN=100005;
const int INF=1e9+5;
map<int,int> mp[MAXN];
map<int,int> vis;
int cnt=0;int lowbit(int t)
{return t&(-t);
}void update(int pos,int t,int val)
{while(t<INF){mp[pos][t]+=val;t+=lowbit(t);}
}int sum(int pos,int t)
{int ans=0;while(t){ans+=mp[pos][t];t-=lowbit(t);}return ans;
}int main()
{int n,cmd,t,x;while(~scanf("%d",&n)){cnt=0;vis.clear();while(n--){scanf("%d%d%d",&cmd,&t,&x);if(cmd==1){if(!vis[x]){vis[x]=++cnt; mp[cnt].clear();}update(vis[x],t,1);}else if(cmd==2){update(vis[x],t,-1);}else if(cmd==3){printf("%d\n",sum(vis[x],t));}}}return 0;
}