1. 程式人生 > >cf#348-E. Little Artem and Time Machine-樹狀陣列+map節點(動態開點樹狀陣列)

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;

}