cf#348-E. Little Artem and Time Machine-树状数组+map节点(动态开点树状数组)

http://codeforces.com/contest/669/problem/E


题意:

题意:有三个操作

    1 x y,在第x秒插入一个y

    2 x y,在第x秒移走一个y

    3 x y, 问第x秒有多少个y


这个操作3可以问之前的时间,也可以问未来的时间。。。不太好离线搞


直接对数值y离散化,对于每个y建一个线段树/树状数组,维护的是时间这个维度,代表某段时间里,这个y值的出现情况


例如在x秒插入一个 y,相当于在y的树状数组里,x这个下标+1。

查询x秒时y的数量,就是相当于在y的树状数组里,【1,x】的和是什么。

这里对于每个值的树状数组不可能真的开一个  1e9的 管辖区间,因为总的访问量只有q,我们采用动态开点的方式即可,这里为了实现方便直接用map替代,缺点是时间复杂度多了一个log,对于本题还算可以接受


时间是q*log1e9*log(玄学),第一个log是树状数组的,第二个是map的(不会算)




代码:

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;

const double pi=acos(-1.0);
double eps=0.000001;
typedef long long  ll;
struct node
{
    int x,y,z;
};
node tt[100005];
int bb[100005];
int idx[100005];
map<int ,int> tree[100050];
struct TREE
{

    int lowbit(int x)
    {
        return x&-x;
    }
    void add(int x,int value,int id)
    {
        for (int i=x; i<=1e9; i=i+lowbit(i))
        {
            tree[id][i]+=value;
        }
    }
    int get(int x,int id)
    {
        int sum=0;
        for (int i=x; i; i-=lowbit(i))
        {
            sum+=tree[id][i];
        }
        return sum;
    }
};
TREE tp[100005];
int main()
{
    int q;
    cin>>q;
    int x,y,z;
    for (int i=1; i<=q; i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        tt[i].x=x,tt[i].y=y,tt[i].z=z;
        bb[i]=z;
    }
    sort(bb+1,bb+1+q);
    int cun=unique(bb+1,bb+1+q)-bb-1;
    for (int i=1; i<=q; i++)
        idx[i]=lower_bound(bb+1,bb+1+cun,tt[i].z)-bb;

    for (int i=1; i<=q; i++)
    {
        int x=tt[i].x,y=tt[i].y;
        if (x==1)
            tp[idx[i]].add(y,1,idx[i]);
        if (x==2 )
            tp[idx[i]].add(y,-1,idx[i]);
        if (x==3)
        {
            int ret=tp[idx[i]].get(y,idx[i]);
            printf("%d\n",ret);
        }
    }

    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值